Commit c8f95e8a by Alexis Hetu Committed by Alexis Hétu

Floating point renderbuffer support

It is now possible to use floating point renderbuffers and read the data back from them. The changes include: - Modified glReadPixels so that it always uses the blitter to copy the data to the external buffer. - Added new types to both Framebuffer and some utility functions. - Added the new ValidReadPixelsFormatType function to validate the glReadPixels format/type combo, which had a bit more possibilities than the RGBA/UNSIGNED BYTE combo previously used. Change-Id: I1726ea57c4f7aa85bf0ffa7f323dc6a16abc34ff Reviewed-on: https://swiftshader-review.googlesource.com/4260Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent f14891d7
...@@ -165,8 +165,10 @@ Context::Context(const egl::Config *config, const Context *shareContext, EGLint ...@@ -165,8 +165,10 @@ Context::Context(const egl::Config *config, const Context *shareContext, EGLint
mState.packAlignment = 4; mState.packAlignment = 4;
mState.unpackInfo.alignment = 4; mState.unpackInfo.alignment = 4;
mState.packRowLength = 0; mState.packRowLength = 0;
mState.packImageHeight = 0;
mState.packSkipPixels = 0; mState.packSkipPixels = 0;
mState.packSkipRows = 0; mState.packSkipRows = 0;
mState.packSkipImages = 0;
mState.unpackInfo.rowLength = 0; mState.unpackInfo.rowLength = 0;
mState.unpackInfo.imageHeight = 0; mState.unpackInfo.imageHeight = 0;
mState.unpackInfo.skipPixels = 0; mState.unpackInfo.skipPixels = 0;
...@@ -848,6 +850,11 @@ void Context::setPackRowLength(GLint rowLength) ...@@ -848,6 +850,11 @@ void Context::setPackRowLength(GLint rowLength)
mState.packRowLength = rowLength; mState.packRowLength = rowLength;
} }
void Context::setPackImageHeight(GLint imageHeight)
{
mState.packImageHeight = imageHeight;
}
void Context::setPackSkipPixels(GLint skipPixels) void Context::setPackSkipPixels(GLint skipPixels)
{ {
mState.packSkipPixels = skipPixels; mState.packSkipPixels = skipPixels;
...@@ -858,6 +865,11 @@ void Context::setPackSkipRows(GLint skipRows) ...@@ -858,6 +865,11 @@ void Context::setPackSkipRows(GLint skipRows)
mState.packSkipRows = skipRows; mState.packSkipRows = skipRows;
} }
void Context::setPackSkipImages(GLint skipImages)
{
mState.packSkipImages = skipImages;
}
void Context::setUnpackRowLength(GLint rowLength) void Context::setUnpackRowLength(GLint rowLength)
{ {
mState.unpackInfo.rowLength = rowLength; mState.unpackInfo.rowLength = rowLength;
...@@ -3262,15 +3274,18 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, ...@@ -3262,15 +3274,18 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if(format != GL_RGBA || type != GL_UNSIGNED_BYTE) GLenum readFormat = framebuffer->getImplementationColorReadFormat();
{ GLenum readType = framebuffer->getImplementationColorReadType();
if(format != framebuffer->getImplementationColorReadFormat() || type != framebuffer->getImplementationColorReadType())
if(!(readFormat == format && readType == type) && !ValidReadPixelsFormatType(readFormat, readType, format, type, clientVersion))
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
}
GLsizei outputPitch = (mState.packRowLength > 0) ? mState.packRowLength : egl::ComputePitch(width, format, type, mState.packAlignment); GLsizei outputPitch = egl::ComputePitch((mState.packRowLength > 0) ? mState.packRowLength : width, format, type, mState.packAlignment);
GLsizei outputHeight = (mState.packImageHeight == 0) ? height : mState.packImageHeight;
pixels = getPixelPackBuffer() ? (unsigned char*)getPixelPackBuffer()->data() + (ptrdiff_t)pixels : (unsigned char*)pixels;
pixels = ((char*)pixels) + (mState.packSkipImages * outputHeight + mState.packSkipRows) * outputPitch + mState.packSkipPixels;
// Sized query sanity check // Sized query sanity check
if(bufSize) if(bufSize)
...@@ -3292,256 +3307,13 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, ...@@ -3292,256 +3307,13 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
x += mState.packSkipPixels; x += mState.packSkipPixels;
y += mState.packSkipRows; y += mState.packSkipRows;
sw::Rect rect = {x, y, x + width, y + height}; sw::Rect rect = {x, y, x + width, y + height};
sw::Rect dstRect = { 0, 0, width, height };
rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight()); rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY); sw::Surface externalSurface(width, height, 1, egl::SelectInternalFormat(format, type), pixels, outputPitch, outputPitch * outputHeight);
unsigned char *dest = getPixelPackBuffer() ? (unsigned char*)getPixelPackBuffer()->data() + (ptrdiff_t)pixels : (unsigned char*)pixels; sw::SliceRect sliceRect(rect);
int inputPitch = (int)renderTarget->getPitch(); sw::SliceRect dstSliceRect(dstRect);
device->blit(renderTarget, sliceRect, &externalSurface, dstSliceRect, false);
for(int j = 0; j < rect.y1 - rect.y0; j++)
{
unsigned short *dest16 = (unsigned short*)dest;
unsigned int *dest32 = (unsigned int*)dest;
if(renderTarget->getInternalFormat() == sw::FORMAT_A8B8G8R8 &&
format == GL_RGBA && type == GL_UNSIGNED_BYTE)
{
memcpy(dest, source, (rect.x1 - rect.x0) * 4);
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&
format == GL_RGBA && type == GL_UNSIGNED_BYTE)
{
for(int i = 0; i < rect.x1 - rect.x0; i++)
{
unsigned int argb = *(unsigned int*)(source + 4 * i);
dest32[i] = (argb & 0xFF00FF00) | ((argb & 0x000000FF) << 16) | ((argb & 0x00FF0000) >> 16);
}
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 &&
format == GL_RGBA && type == GL_UNSIGNED_BYTE)
{
for(int i = 0; i < rect.x1 - rect.x0; i++)
{
unsigned int xrgb = *(unsigned int*)(source + 4 * i);
dest32[i] = (xrgb & 0xFF00FF00) | ((xrgb & 0x000000FF) << 16) | ((xrgb & 0x00FF0000) >> 16) | 0xFF000000;
}
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_X8R8G8B8 &&
format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
{
for(int i = 0; i < rect.x1 - rect.x0; i++)
{
unsigned int xrgb = *(unsigned int*)(source + 4 * i);
dest32[i] = xrgb | 0xFF000000;
}
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_A8R8G8B8 &&
format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
{
memcpy(dest, source, (rect.x1 - rect.x0) * 4);
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_A16B16G16R16F &&
format == GL_RGBA && (type == GL_HALF_FLOAT || type == GL_HALF_FLOAT_OES))
{
memcpy(dest, source, (rect.x1 - rect.x0) * 8);
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_A32B32G32R32F &&
format == GL_RGBA && type == GL_FLOAT)
{
memcpy(dest, source, (rect.x1 - rect.x0) * 16);
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_A1R5G5B5 &&
format == GL_BGRA_EXT && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)
{
memcpy(dest, source, (rect.x1 - rect.x0) * 2);
}
else if(renderTarget->getInternalFormat() == sw::FORMAT_R5G6B5 &&
format == 0x80E0 && type == GL_UNSIGNED_SHORT_5_6_5) // GL_BGR_EXT
{
memcpy(dest, source, (rect.x1 - rect.x0) * 2);
}
else
{
for(int i = 0; i < rect.x1 - rect.x0; i++)
{
float r;
float g;
float b;
float a;
switch(renderTarget->getInternalFormat())
{
case sw::FORMAT_R5G6B5:
{
unsigned short rgb = *(unsigned short*)(source + 2 * i);
a = 1.0f;
b = (rgb & 0x001F) * (1.0f / 0x001F);
g = (rgb & 0x07E0) * (1.0f / 0x07E0);
r = (rgb & 0xF800) * (1.0f / 0xF800);
}
break;
case sw::FORMAT_A1R5G5B5:
{
unsigned short argb = *(unsigned short*)(source + 2 * i);
a = (argb & 0x8000) ? 1.0f : 0.0f;
b = (argb & 0x001F) * (1.0f / 0x001F);
g = (argb & 0x03E0) * (1.0f / 0x03E0);
r = (argb & 0x7C00) * (1.0f / 0x7C00);
}
break;
case sw::FORMAT_A8R8G8B8:
{
unsigned int argb = *(unsigned int*)(source + 4 * i);
a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
}
break;
case sw::FORMAT_A8B8G8R8:
{
unsigned int abgr = *(unsigned int*)(source + 4 * i);
a = (abgr & 0xFF000000) * (1.0f / 0xFF000000);
b = (abgr & 0x00FF0000) * (1.0f / 0x00FF0000);
g = (abgr & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (abgr & 0x000000FF) * (1.0f / 0x000000FF);
}
break;
case sw::FORMAT_X8R8G8B8:
{
unsigned int xrgb = *(unsigned int*)(source + 4 * i);
a = 1.0f;
b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
}
break;
case sw::FORMAT_X8B8G8R8:
{
unsigned int xbgr = *(unsigned int*)(source + 4 * i);
a = 1.0f;
b = (xbgr & 0x00FF0000) * (1.0f / 0x00FF0000);
g = (xbgr & 0x0000FF00) * (1.0f / 0x0000FF00);
r = (xbgr & 0x000000FF) * (1.0f / 0x000000FF);
}
break;
case sw::FORMAT_A2R10G10B10:
{
unsigned int argb = *(unsigned int*)(source + 4 * i);
a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
}
break;
case sw::FORMAT_A32B32G32R32F:
{
r = *((float*)(source + 16 * i) + 0);
g = *((float*)(source + 16 * i) + 1);
b = *((float*)(source + 16 * i) + 2);
a = *((float*)(source + 16 * i) + 3);
}
break;
case sw::FORMAT_A16B16G16R16F:
{
r = (float)*((sw::half*)(source + 8 * i) + 0);
g = (float)*((sw::half*)(source + 8 * i) + 1);
b = (float)*((sw::half*)(source + 8 * i) + 2);
a = (float)*((sw::half*)(source + 8 * i) + 3);
}
break;
default:
UNIMPLEMENTED(); // FIXME
UNREACHABLE(renderTarget->getInternalFormat());
}
switch(format)
{
case GL_RGBA:
switch(type)
{
case GL_UNSIGNED_BYTE:
dest[4 * i + 0] = (unsigned char)(255 * r + 0.5f);
dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f);
dest[4 * i + 2] = (unsigned char)(255 * b + 0.5f);
dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f);
break;
default: UNREACHABLE(type);
}
break;
case GL_BGRA_EXT:
switch(type)
{
case GL_UNSIGNED_BYTE:
dest[4 * i + 0] = (unsigned char)(255 * b + 0.5f);
dest[4 * i + 1] = (unsigned char)(255 * g + 0.5f);
dest[4 * i + 2] = (unsigned char)(255 * r + 0.5f);
dest[4 * i + 3] = (unsigned char)(255 * a + 0.5f);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
// this type is packed as follows:
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// --------------------------------------------------------------------------------
// | 4th | 3rd | 2nd | 1st component |
// --------------------------------------------------------------------------------
// in the case of BGRA_EXT, B is the first component, G the second, and so forth.
dest16[i] =
((unsigned short)(15 * a + 0.5f) << 12)|
((unsigned short)(15 * r + 0.5f) << 8) |
((unsigned short)(15 * g + 0.5f) << 4) |
((unsigned short)(15 * b + 0.5f) << 0);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
// According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
// this type is packed as follows:
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// --------------------------------------------------------------------------------
// | 4th | 3rd | 2nd | 1st component |
// --------------------------------------------------------------------------------
// in the case of BGRA_EXT, B is the first component, G the second, and so forth.
dest16[i] =
((unsigned short)( a + 0.5f) << 15) |
((unsigned short)(31 * r + 0.5f) << 10) |
((unsigned short)(31 * g + 0.5f) << 5) |
((unsigned short)(31 * b + 0.5f) << 0);
break;
default: UNREACHABLE(type);
}
break;
case GL_RGB:
switch(type)
{
case GL_UNSIGNED_SHORT_5_6_5:
dest16[i] =
((unsigned short)(31 * b + 0.5f) << 0) |
((unsigned short)(63 * g + 0.5f) << 5) |
((unsigned short)(31 * r + 0.5f) << 11);
break;
default: UNREACHABLE(type);
}
break;
default: UNREACHABLE(format);
}
}
}
source += inputPitch;
dest += outputPitch;
}
renderTarget->unlock();
renderTarget->release();
} }
void Context::clear(GLbitfield mask) void Context::clear(GLbitfield mask)
......
...@@ -397,8 +397,10 @@ struct State ...@@ -397,8 +397,10 @@ struct State
egl::Image::UnpackInfo unpackInfo; egl::Image::UnpackInfo unpackInfo;
GLint packAlignment; GLint packAlignment;
GLint packRowLength; GLint packRowLength;
GLint packImageHeight;
GLint packSkipPixels; GLint packSkipPixels;
GLint packSkipRows; GLint packSkipRows;
GLint packSkipImages;
}; };
class Context : public egl::Context class Context : public egl::Context
...@@ -511,8 +513,10 @@ public: ...@@ -511,8 +513,10 @@ public:
void setPackAlignment(GLint alignment); void setPackAlignment(GLint alignment);
void setPackRowLength(GLint rowLength); void setPackRowLength(GLint rowLength);
void setPackImageHeight(GLint imageHeight);
void setPackSkipPixels(GLint skipPixels); void setPackSkipPixels(GLint skipPixels);
void setPackSkipRows(GLint skipRows); void setPackSkipRows(GLint skipRows);
void setPackSkipImages(GLint skipImages);
// These create and destroy methods are merely pass-throughs to // These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types // ResourceManager, which owns these object types
......
...@@ -284,7 +284,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples) ...@@ -284,7 +284,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
if(mColorbufferType[i] == GL_RENDERBUFFER) if(mColorbufferType[i] == GL_RENDERBUFFER)
{ {
if(!es2::IsColorRenderable(colorbuffer->getFormat())) if(!es2::IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
{ {
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
} }
...@@ -448,14 +448,49 @@ GLenum Framebuffer::getImplementationColorReadFormat() ...@@ -448,14 +448,49 @@ GLenum Framebuffer::getImplementationColorReadFormat()
// Don't return GL_RGBA since that's always supported. Provide a second option here. // Don't return GL_RGBA since that's always supported. Provide a second option here.
switch(colorbuffer->getInternalFormat()) switch(colorbuffer->getInternalFormat())
{ {
case sw::FORMAT_A16B16G16R16F: return GL_BGRA_EXT; case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_A32B32G32R32F: return GL_BGRA_EXT; case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_A8R8G8B8: return GL_BGRA_EXT; case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_A8B8G8R8: return GL_BGRA_EXT; case sw::FORMAT_A16B16G16R16UI:
case sw::FORMAT_X8R8G8B8: return 0x80E0; // GL_BGR_EXT case sw::FORMAT_A32B32G32R32I:
case sw::FORMAT_X8B8G8R8: return 0x80E0; // GL_BGR_EXT case sw::FORMAT_A32B32G32R32UI:return GL_RGBA_INTEGER;
case sw::FORMAT_A2B10G10R10: return GL_RGB10_A2;
case sw::FORMAT_A8B8G8R8I_SNORM:
case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_A32B32G32R32F:
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_A1R5G5B5: return GL_BGRA_EXT; case sw::FORMAT_A1R5G5B5: return GL_BGRA_EXT;
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_X32B32G32R32UI:return GL_RGB_INTEGER;
case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_X8B8G8R8:
case sw::FORMAT_X8R8G8B8:
case sw::FORMAT_R5G6B5: return 0x80E0; // GL_BGR_EXT case sw::FORMAT_R5G6B5: return 0x80E0; // GL_BGR_EXT
case sw::FORMAT_G8R8I:
case sw::FORMAT_G8R8UI:
case sw::FORMAT_G16R16I:
case sw::FORMAT_G16R16UI:
case sw::FORMAT_G32R32I:
case sw::FORMAT_G32R32UI: return GL_RG_INTEGER;
case sw::FORMAT_G8R8:
case sw::FORMAT_G8R8I_SNORM:
case sw::FORMAT_G16R16F:
case sw::FORMAT_G32R32F: return GL_RG;
case sw::FORMAT_R8I:
case sw::FORMAT_R8UI:
case sw::FORMAT_R16I:
case sw::FORMAT_R16UI:
case sw::FORMAT_R32I:
case sw::FORMAT_R32UI: return GL_RED_INTEGER;
case sw::FORMAT_R8:
case sw::FORMAT_R8I_SNORM:
case sw::FORMAT_R16F:
case sw::FORMAT_R32F: return GL_RED;
default: default:
UNREACHABLE(colorbuffer->getInternalFormat()); UNREACHABLE(colorbuffer->getInternalFormat());
} }
...@@ -472,12 +507,49 @@ GLenum Framebuffer::getImplementationColorReadType() ...@@ -472,12 +507,49 @@ GLenum Framebuffer::getImplementationColorReadType()
{ {
switch(colorbuffer->getInternalFormat()) switch(colorbuffer->getInternalFormat())
{ {
case sw::FORMAT_A16B16G16R16F: return (egl::getClientVersion() < 3) ? GL_HALF_FLOAT_OES : GL_HALF_FLOAT; case sw::FORMAT_R16F:
case sw::FORMAT_G16R16F:
case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_R32F:
case sw::FORMAT_G32R32F:
case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F: return GL_FLOAT; case sw::FORMAT_A32B32G32R32F: return GL_FLOAT;
case sw::FORMAT_A8R8G8B8: return GL_UNSIGNED_BYTE; case sw::FORMAT_R8I_SNORM:
case sw::FORMAT_A8B8G8R8: return GL_UNSIGNED_BYTE; case sw::FORMAT_G8R8I_SNORM:
case sw::FORMAT_X8R8G8B8: return GL_UNSIGNED_BYTE; case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_A8B8G8R8I_SNORM:return GL_BYTE;
case sw::FORMAT_R8:
case sw::FORMAT_G8R8:
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8:
case sw::FORMAT_X8B8G8R8: return GL_UNSIGNED_BYTE; case sw::FORMAT_X8B8G8R8: return GL_UNSIGNED_BYTE;
case sw::FORMAT_R8I:
case sw::FORMAT_G8R8I:
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_R16I:
case sw::FORMAT_G16R16I:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_R32I:
case sw::FORMAT_G32R32I:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_A32B32G32R32I: return GL_INT;
case sw::FORMAT_R8UI:
case sw::FORMAT_G8R8UI:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_R16UI:
case sw::FORMAT_G16R16UI:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_A16B16G16R16UI:
case sw::FORMAT_R32UI:
case sw::FORMAT_G32R32UI:
case sw::FORMAT_X32B32G32R32UI:
case sw::FORMAT_A32B32G32R32UI:return GL_UNSIGNED_INT;
case sw::FORMAT_A2B10G10R10: return GL_UNSIGNED_INT_10_10_10_2_OES;
case sw::FORMAT_A1R5G5B5: return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT; case sw::FORMAT_A1R5G5B5: return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
case sw::FORMAT_R5G6B5: return GL_UNSIGNED_SHORT_5_6_5; case sw::FORMAT_R5G6B5: return GL_UNSIGNED_SHORT_5_6_5;
default: default:
......
...@@ -4744,6 +4744,14 @@ void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum ...@@ -4744,6 +4744,14 @@ void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum
case GL_RGBA16I: case GL_RGBA16I:
case GL_RGBA32I: case GL_RGBA32I:
case GL_RGBA32UI: case GL_RGBA32UI:
case GL_R16F:
case GL_RG16F:
case GL_R11F_G11F_B10F:
case GL_RGBA16F:
case GL_R32F:
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
if(clientVersion < 3) if(clientVersion < 3)
{ {
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
...@@ -4760,6 +4768,7 @@ void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum ...@@ -4760,6 +4768,7 @@ void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum
context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples)); context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
break; break;
case GL_DEPTH32F_STENCIL8: case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_COMPONENT32_OES:
if(clientVersion < 3) if(clientVersion < 3)
{ {
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
......
...@@ -3951,7 +3951,7 @@ GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internal ...@@ -3951,7 +3951,7 @@ GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internal
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
if(!IsColorRenderable(internalformat) && !IsDepthRenderable(internalformat) && !IsStencilRenderable(internalformat)) if(!IsColorRenderable(internalformat, egl::getClientVersion()) && !IsDepthRenderable(internalformat) && !IsStencilRenderable(internalformat))
{ {
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
......
...@@ -377,6 +377,66 @@ namespace es2 ...@@ -377,6 +377,66 @@ namespace es2
} }
} }
bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion)
{
switch(format)
{
case GL_RGBA:
switch(type)
{
case GL_UNSIGNED_BYTE:
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
return (clientVersion >= 3) && (internalFormat == GL_RGB10_A2);
case GL_FLOAT:
return (clientVersion >= 3) && (internalType == GL_FLOAT);
default:
return false;
}
break;
case GL_RGBA_INTEGER:
if(clientVersion < 3)
{
return false;
}
switch(type)
{
case GL_INT:
if(internalType != GL_INT)
{
return false;
}
break;
case GL_UNSIGNED_INT:
if(internalType != GL_UNSIGNED_INT)
{
return false;
}
break;
default:
return false;
}
break;
case GL_BGRA_EXT:
switch(type)
{
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
break;
default:
return false;
}
break;
case GL_RG_EXT:
case GL_RED_EXT:
return (clientVersion >= 3) && (type == GL_UNSIGNED_BYTE);
default:
return false;
}
return true;
}
bool IsDepthTexture(GLenum format) bool IsDepthTexture(GLenum format)
{ {
return format == GL_DEPTH_COMPONENT || return format == GL_DEPTH_COMPONENT ||
...@@ -535,7 +595,7 @@ namespace es2 ...@@ -535,7 +595,7 @@ namespace es2
} }
} }
bool IsColorRenderable(GLenum internalformat) bool IsColorRenderable(GLenum internalformat, egl::GLint clientVersion)
{ {
switch(internalformat) switch(internalformat)
{ {
...@@ -568,7 +628,18 @@ namespace es2 ...@@ -568,7 +628,18 @@ namespace es2
case GL_RGB8_OES: case GL_RGB8_OES:
case GL_RGBA8_OES: case GL_RGBA8_OES:
return true; return true;
case GL_R16F:
case GL_RG16F:
case GL_R11F_G11F_B10F:
case GL_RGB16F:
case GL_RGBA16F:
case GL_R32F:
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
return clientVersion >= 3;
case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F: case GL_DEPTH_COMPONENT32F:
case GL_DEPTH32F_STENCIL8: case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT16:
...@@ -587,6 +658,7 @@ namespace es2 ...@@ -587,6 +658,7 @@ namespace es2
switch(internalformat) switch(internalformat)
{ {
case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F: case GL_DEPTH_COMPONENT32F:
case GL_DEPTH32F_STENCIL8: case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT16:
...@@ -621,6 +693,15 @@ namespace es2 ...@@ -621,6 +693,15 @@ namespace es2
case GL_RGB565: case GL_RGB565:
case GL_RGB8_OES: case GL_RGB8_OES:
case GL_RGBA8_OES: case GL_RGBA8_OES:
case GL_R16F:
case GL_RG16F:
case GL_R11F_G11F_B10F:
case GL_RGB16F:
case GL_RGBA16F:
case GL_R32F:
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
return false; return false;
default: default:
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -665,8 +746,18 @@ namespace es2 ...@@ -665,8 +746,18 @@ namespace es2
case GL_RGB565: case GL_RGB565:
case GL_RGB8_OES: case GL_RGB8_OES:
case GL_RGBA8_OES: case GL_RGBA8_OES:
case GL_R16F:
case GL_RG16F:
case GL_R11F_G11F_B10F:
case GL_RGB16F:
case GL_RGBA16F:
case GL_R32F:
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F: case GL_DEPTH_COMPONENT32F:
return false; return false;
default: default:
...@@ -965,7 +1056,46 @@ namespace es2sw ...@@ -965,7 +1056,46 @@ namespace es2sw
case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT16:
case GL_STENCIL_INDEX8: case GL_STENCIL_INDEX8:
case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8; case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
default: UNREACHABLE(format); return sw::FORMAT_A8B8G8R8; case GL_DEPTH_COMPONENT32_OES:return sw::FORMAT_D32;
case GL_R8: return sw::FORMAT_R8;
case GL_RG8: return sw::FORMAT_G8R8;
case GL_R8I: return sw::FORMAT_R8I;
case GL_RG8I: return sw::FORMAT_G8R8I;
case GL_RGB8I: return sw::FORMAT_X8B8G8R8I;
case GL_RGBA8I: return sw::FORMAT_A8B8G8R8I;
case GL_R8UI: return sw::FORMAT_R8UI;
case GL_RG8UI: return sw::FORMAT_G8R8UI;
case GL_RGB8UI: return sw::FORMAT_X8B8G8R8UI;
case GL_RGBA8UI: return sw::FORMAT_A8B8G8R8UI;
case GL_R16I: return sw::FORMAT_R16I;
case GL_RG16I: return sw::FORMAT_G16R16I;
case GL_RGB16I: return sw::FORMAT_X16B16G16R16I;
case GL_RGBA16I: return sw::FORMAT_A16B16G16R16I;
case GL_R16UI: return sw::FORMAT_R16UI;
case GL_RG16UI: return sw::FORMAT_G16R16UI;
case GL_RGB16UI: return sw::FORMAT_X16B16G16R16UI;
case GL_RGB10_A2UI:
case GL_RGBA16UI: return sw::FORMAT_A16B16G16R16UI;
case GL_R32I: return sw::FORMAT_R32I;
case GL_RG32I: return sw::FORMAT_G32R32I;
case GL_RGB32I: return sw::FORMAT_X32B32G32R32I;
case GL_RGBA32I: return sw::FORMAT_A32B32G32R32I;
case GL_R32UI: return sw::FORMAT_R32UI;
case GL_RG32UI: return sw::FORMAT_G32R32UI;
case GL_RGB32UI: return sw::FORMAT_X32B32G32R32UI;
case GL_RGBA32UI: return sw::FORMAT_A32B32G32R32UI;
case GL_R16F: return sw::FORMAT_R16F;
case GL_RG16F: return sw::FORMAT_G16R16F;
case GL_R11F_G11F_B10F:
case GL_RGB16F: return sw::FORMAT_B16G16R16F;
case GL_RGBA16F: return sw::FORMAT_A16B16G16R16F;
case GL_R32F: return sw::FORMAT_R32F;
case GL_RG32F: return sw::FORMAT_G32R32F;
case GL_RGB32F: return sw::FORMAT_B32G32R32F;
case GL_RGBA32F: return sw::FORMAT_A32B32G32R32F;
case GL_RGB10_A2: return sw::FORMAT_A2B10G10R10;
case GL_SRGB8_ALPHA8: // FIXME: Implement SRGB
default: UNREACHABLE(format); return sw::FORMAT_NULL;
} }
} }
} }
...@@ -1002,14 +1132,23 @@ namespace sw2es ...@@ -1002,14 +1132,23 @@ namespace sw2es
switch(colorFormat) switch(colorFormat)
{ {
case sw::FORMAT_A16B16G16R16F: case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_A16B16G16R16UI:
return 16; return 16;
case sw::FORMAT_A32B32G32R32F: case sw::FORMAT_A32B32G32R32F:
case sw::FORMAT_A32B32G32R32I:
case sw::FORMAT_A32B32G32R32UI:
return 32; return 32;
case sw::FORMAT_A2R10G10B10: case sw::FORMAT_A2R10G10B10:
return 2; return 2;
case sw::FORMAT_A8R8G8B8: case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8: case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_A8B8G8R8I_SNORM:
return 8; return 8;
case sw::FORMAT_A2B10G10R10:
return 2;
case sw::FORMAT_A1R5G5B5: case sw::FORMAT_A1R5G5B5:
return 1; return 1;
case sw::FORMAT_X8R8G8B8: case sw::FORMAT_X8R8G8B8:
...@@ -1025,16 +1164,53 @@ namespace sw2es ...@@ -1025,16 +1164,53 @@ namespace sw2es
{ {
switch(colorFormat) switch(colorFormat)
{ {
case sw::FORMAT_R16F:
case sw::FORMAT_G16R16F:
case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F: case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_R16I:
case sw::FORMAT_G16R16I:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_R16UI:
case sw::FORMAT_G16R16UI:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_A16B16G16R16UI:
return 16; return 16;
case sw::FORMAT_R32F:
case sw::FORMAT_G32R32F:
case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F: case sw::FORMAT_A32B32G32R32F:
case sw::FORMAT_R32I:
case sw::FORMAT_G32R32I:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_A32B32G32R32I:
case sw::FORMAT_R32UI:
case sw::FORMAT_G32R32UI:
case sw::FORMAT_X32B32G32R32UI:
case sw::FORMAT_A32B32G32R32UI:
return 32; return 32;
case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10: case sw::FORMAT_A2R10G10B10:
return 10; return 10;
case sw::FORMAT_A8R8G8B8: case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8: case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8: case sw::FORMAT_X8R8G8B8:
case sw::FORMAT_X8B8G8R8: case sw::FORMAT_X8B8G8R8:
case sw::FORMAT_R8:
case sw::FORMAT_G8R8:
case sw::FORMAT_R8I:
case sw::FORMAT_G8R8I:
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_R8UI:
case sw::FORMAT_G8R8UI:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_R8I_SNORM:
case sw::FORMAT_G8R8I_SNORM:
case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_A8B8G8R8I_SNORM:
return 8; return 8;
case sw::FORMAT_A1R5G5B5: case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5: case sw::FORMAT_R5G6B5:
...@@ -1048,16 +1224,43 @@ namespace sw2es ...@@ -1048,16 +1224,43 @@ namespace sw2es
{ {
switch(colorFormat) switch(colorFormat)
{ {
case sw::FORMAT_G16R16F:
case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F: case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_G16R16I:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_G16R16UI:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_A16B16G16R16UI:
return 16; return 16;
case sw::FORMAT_G32R32F:
case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F: case sw::FORMAT_A32B32G32R32F:
case sw::FORMAT_G32R32I:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_A32B32G32R32I:
case sw::FORMAT_G32R32UI:
case sw::FORMAT_X32B32G32R32UI:
case sw::FORMAT_A32B32G32R32UI:
return 32; return 32;
case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10: case sw::FORMAT_A2R10G10B10:
return 10; return 10;
case sw::FORMAT_A8R8G8B8: case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8: case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8: case sw::FORMAT_X8R8G8B8:
case sw::FORMAT_X8B8G8R8: case sw::FORMAT_X8B8G8R8:
case sw::FORMAT_G8R8:
case sw::FORMAT_G8R8I:
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_G8R8UI:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_G8R8I_SNORM:
case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_A8B8G8R8I_SNORM:
return 8; return 8;
case sw::FORMAT_A1R5G5B5: case sw::FORMAT_A1R5G5B5:
return 5; return 5;
...@@ -1072,16 +1275,33 @@ namespace sw2es ...@@ -1072,16 +1275,33 @@ namespace sw2es
{ {
switch(colorFormat) switch(colorFormat)
{ {
case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F: case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_A16B16G16R16UI:
return 16; return 16;
case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F: case sw::FORMAT_A32B32G32R32F:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_A32B32G32R32I:
case sw::FORMAT_X32B32G32R32UI:
case sw::FORMAT_A32B32G32R32UI:
return 32; return 32;
case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10: case sw::FORMAT_A2R10G10B10:
return 10; return 10;
case sw::FORMAT_A8R8G8B8: case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8: case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8: case sw::FORMAT_X8R8G8B8:
case sw::FORMAT_X8B8G8R8: case sw::FORMAT_X8B8G8R8:
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_A8B8G8R8I_SNORM:
return 8; return 8;
case sw::FORMAT_A1R5G5B5: case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5: case sw::FORMAT_R5G6B5:
...@@ -1134,9 +1354,44 @@ namespace sw2es ...@@ -1134,9 +1354,44 @@ namespace sw2es
case GL_COLOR_ATTACHMENT15: case GL_COLOR_ATTACHMENT15:
switch(format) switch(format)
{ {
case sw::FORMAT_R8I:
case sw::FORMAT_G8R8I:
case sw::FORMAT_X8B8G8R8I:
case sw::FORMAT_A8B8G8R8I:
case sw::FORMAT_R16I:
case sw::FORMAT_G16R16I:
case sw::FORMAT_X16B16G16R16I:
case sw::FORMAT_A16B16G16R16I:
case sw::FORMAT_R32I:
case sw::FORMAT_G32R32I:
case sw::FORMAT_X32B32G32R32I:
case sw::FORMAT_A32B32G32R32I:
return GL_INT;
case sw::FORMAT_R8UI:
case sw::FORMAT_G8R8UI:
case sw::FORMAT_X8B8G8R8UI:
case sw::FORMAT_A8B8G8R8UI:
case sw::FORMAT_R16UI:
case sw::FORMAT_G16R16UI:
case sw::FORMAT_X16B16G16R16UI:
case sw::FORMAT_A16B16G16R16UI:
case sw::FORMAT_R32UI:
case sw::FORMAT_G32R32UI:
case sw::FORMAT_X32B32G32R32UI:
case sw::FORMAT_A32B32G32R32UI:
return GL_UNSIGNED_INT;
case sw::FORMAT_R16F:
case sw::FORMAT_G16R16F:
case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F: case sw::FORMAT_A16B16G16R16F:
case sw::FORMAT_R32F:
case sw::FORMAT_G32R32F:
case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F: case sw::FORMAT_A32B32G32R32F:
return GL_FLOAT; return GL_FLOAT;
case sw::FORMAT_R8:
case sw::FORMAT_G8R8:
case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10: case sw::FORMAT_A2R10G10B10:
case sw::FORMAT_A8R8G8B8: case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8: case sw::FORMAT_A8B8G8R8:
...@@ -1145,6 +1400,11 @@ namespace sw2es ...@@ -1145,6 +1400,11 @@ namespace sw2es
case sw::FORMAT_A1R5G5B5: case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5: case sw::FORMAT_R5G6B5:
return GL_UNSIGNED_NORMALIZED; return GL_UNSIGNED_NORMALIZED;
case sw::FORMAT_R8I_SNORM:
case sw::FORMAT_X8B8G8R8I_SNORM:
case sw::FORMAT_A8B8G8R8I_SNORM:
case sw::FORMAT_G8R8I_SNORM:
return GL_SIGNED_NORMALIZED;
default: default:
UNREACHABLE(format); UNREACHABLE(format);
return 0; return 0;
......
...@@ -42,6 +42,7 @@ namespace es2 ...@@ -42,6 +42,7 @@ namespace es2
bool IsCompressed(GLenum format, egl::GLint clientVersion); bool IsCompressed(GLenum format, egl::GLint clientVersion);
GLenum ValidateCompressedFormat(GLenum format, egl::GLint clientVersion, bool expectCompressedFormats); GLenum ValidateCompressedFormat(GLenum format, egl::GLint clientVersion, bool expectCompressedFormats);
bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion);
bool IsDepthTexture(GLenum format); bool IsDepthTexture(GLenum format);
bool IsStencilTexture(GLenum format); bool IsStencilTexture(GLenum format);
bool IsCubemapTextureTarget(GLenum target); bool IsCubemapTextureTarget(GLenum target);
...@@ -49,7 +50,7 @@ namespace es2 ...@@ -49,7 +50,7 @@ namespace es2
bool IsTextureTarget(GLenum target); bool IsTextureTarget(GLenum target);
bool CheckTextureFormatType(GLenum format, GLenum type, egl::GLint clientVersion); bool CheckTextureFormatType(GLenum format, GLenum type, egl::GLint clientVersion);
bool IsColorRenderable(GLenum internalformat); bool IsColorRenderable(GLenum internalformat, egl::GLint clientVersion);
bool IsDepthRenderable(GLenum internalformat); bool IsDepthRenderable(GLenum internalformat);
bool IsStencilRenderable(GLenum internalformat); bool IsStencilRenderable(GLenum internalformat);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment