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/4260
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index e90ddc9..5826ec9 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -165,8 +165,10 @@
mState.packAlignment = 4;
mState.unpackInfo.alignment = 4;
mState.packRowLength = 0;
+ mState.packImageHeight = 0;
mState.packSkipPixels = 0;
mState.packSkipRows = 0;
+ mState.packSkipImages = 0;
mState.unpackInfo.rowLength = 0;
mState.unpackInfo.imageHeight = 0;
mState.unpackInfo.skipPixels = 0;
@@ -848,6 +850,11 @@
mState.packRowLength = rowLength;
}
+void Context::setPackImageHeight(GLint imageHeight)
+{
+ mState.packImageHeight = imageHeight;
+}
+
void Context::setPackSkipPixels(GLint skipPixels)
{
mState.packSkipPixels = skipPixels;
@@ -858,6 +865,11 @@
mState.packSkipRows = skipRows;
}
+void Context::setPackSkipImages(GLint skipImages)
+{
+ mState.packSkipImages = skipImages;
+}
+
void Context::setUnpackRowLength(GLint rowLength)
{
mState.unpackInfo.rowLength = rowLength;
@@ -3262,15 +3274,18 @@
return error(GL_INVALID_OPERATION);
}
- if(format != GL_RGBA || type != GL_UNSIGNED_BYTE)
+ GLenum readFormat = framebuffer->getImplementationColorReadFormat();
+ GLenum readType = framebuffer->getImplementationColorReadType();
+
+ if(!(readFormat == format && readType == type) && !ValidReadPixelsFormatType(readFormat, readType, format, type, clientVersion))
{
- if(format != framebuffer->getImplementationColorReadFormat() || type != framebuffer->getImplementationColorReadType())
- {
- 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
if(bufSize)
@@ -3292,256 +3307,13 @@
x += mState.packSkipPixels;
y += mState.packSkipRows;
sw::Rect rect = {x, y, x + width, y + height};
+ sw::Rect dstRect = { 0, 0, width, height };
rect.clip(0, 0, renderTarget->getWidth(), renderTarget->getHeight());
- unsigned char *source = (unsigned char*)renderTarget->lock(rect.x0, rect.y0, sw::LOCK_READONLY);
- unsigned char *dest = getPixelPackBuffer() ? (unsigned char*)getPixelPackBuffer()->data() + (ptrdiff_t)pixels : (unsigned char*)pixels;
- int inputPitch = (int)renderTarget->getPitch();
-
- 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();
+ sw::Surface externalSurface(width, height, 1, egl::SelectInternalFormat(format, type), pixels, outputPitch, outputPitch * outputHeight);
+ sw::SliceRect sliceRect(rect);
+ sw::SliceRect dstSliceRect(dstRect);
+ device->blit(renderTarget, sliceRect, &externalSurface, dstSliceRect, false);
}
void Context::clear(GLbitfield mask)
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 545d442..4d7e7fa 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -397,8 +397,10 @@
egl::Image::UnpackInfo unpackInfo;
GLint packAlignment;
GLint packRowLength;
+ GLint packImageHeight;
GLint packSkipPixels;
GLint packSkipRows;
+ GLint packSkipImages;
};
class Context : public egl::Context
@@ -511,8 +513,10 @@
void setPackAlignment(GLint alignment);
void setPackRowLength(GLint rowLength);
+ void setPackImageHeight(GLint imageHeight);
void setPackSkipPixels(GLint skipPixels);
void setPackSkipRows(GLint skipRows);
+ void setPackSkipImages(GLint skipImages);
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index 3dc9f2f..6473473 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -284,7 +284,7 @@
if(mColorbufferType[i] == GL_RENDERBUFFER)
{
- if(!es2::IsColorRenderable(colorbuffer->getFormat()))
+ if(!es2::IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
@@ -448,14 +448,49 @@
// Don't return GL_RGBA since that's always supported. Provide a second option here.
switch(colorbuffer->getInternalFormat())
{
- case sw::FORMAT_A16B16G16R16F: return GL_BGRA_EXT;
- case sw::FORMAT_A32B32G32R32F: return GL_BGRA_EXT;
- case sw::FORMAT_A8R8G8B8: return GL_BGRA_EXT;
- case sw::FORMAT_A8B8G8R8: return GL_BGRA_EXT;
- case sw::FORMAT_X8R8G8B8: return 0x80E0; // GL_BGR_EXT
- case sw::FORMAT_X8B8G8R8: return 0x80E0; // GL_BGR_EXT
+ case sw::FORMAT_A8B8G8R8I:
+ case sw::FORMAT_A8B8G8R8UI:
+ case sw::FORMAT_A16B16G16R16I:
+ case sw::FORMAT_A16B16G16R16UI:
+ case sw::FORMAT_A32B32G32R32I:
+ 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_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_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:
UNREACHABLE(colorbuffer->getInternalFormat());
}
@@ -472,12 +507,49 @@
{
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_A8R8G8B8: return GL_UNSIGNED_BYTE;
- case sw::FORMAT_A8B8G8R8: return GL_UNSIGNED_BYTE;
- case sw::FORMAT_X8R8G8B8: return GL_UNSIGNED_BYTE;
+ case sw::FORMAT_R8I_SNORM:
+ case sw::FORMAT_G8R8I_SNORM:
+ 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_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_R5G6B5: return GL_UNSIGNED_SHORT_5_6_5;
default:
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 8836945..e230759 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -4744,6 +4744,14 @@
case GL_RGBA16I:
case GL_RGBA32I:
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)
{
return error(GL_INVALID_ENUM);
@@ -4760,6 +4768,7 @@
context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
break;
case GL_DEPTH32F_STENCIL8:
+ case GL_DEPTH_COMPONENT32_OES:
if(clientVersion < 3)
{
return error(GL_INVALID_ENUM);
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index f756918..2c99a87 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -3951,7 +3951,7 @@
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);
}
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 6442993..d7ec68b 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -377,6 +377,66 @@
}
}
+ 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)
{
return format == GL_DEPTH_COMPONENT ||
@@ -535,7 +595,7 @@
}
}
- bool IsColorRenderable(GLenum internalformat)
+ bool IsColorRenderable(GLenum internalformat, egl::GLint clientVersion)
{
switch(internalformat)
{
@@ -568,7 +628,18 @@
case GL_RGB8_OES:
case GL_RGBA8_OES:
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_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_COMPONENT16:
@@ -587,6 +658,7 @@
switch(internalformat)
{
case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F:
case GL_DEPTH32F_STENCIL8:
case GL_DEPTH_COMPONENT16:
@@ -621,6 +693,15 @@
case GL_RGB565:
case GL_RGB8_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;
default:
UNIMPLEMENTED();
@@ -665,8 +746,18 @@
case GL_RGB565:
case GL_RGB8_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_COMPONENT24:
+ case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F:
return false;
default:
@@ -965,7 +1056,46 @@
case GL_DEPTH_COMPONENT16:
case GL_STENCIL_INDEX8:
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 @@
switch(colorFormat)
{
case sw::FORMAT_A16B16G16R16F:
+ case sw::FORMAT_A16B16G16R16I:
+ case sw::FORMAT_A16B16G16R16UI:
return 16;
case sw::FORMAT_A32B32G32R32F:
+ case sw::FORMAT_A32B32G32R32I:
+ case sw::FORMAT_A32B32G32R32UI:
return 32;
case sw::FORMAT_A2R10G10B10:
return 2;
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
+ case sw::FORMAT_A8B8G8R8I:
+ case sw::FORMAT_A8B8G8R8UI:
+ case sw::FORMAT_A8B8G8R8I_SNORM:
return 8;
+ case sw::FORMAT_A2B10G10R10:
+ return 2;
case sw::FORMAT_A1R5G5B5:
return 1;
case sw::FORMAT_X8R8G8B8:
@@ -1025,16 +1164,53 @@
{
switch(colorFormat)
{
+ case sw::FORMAT_R16F:
+ case sw::FORMAT_G16R16F:
+ case sw::FORMAT_B16G16R16F:
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;
+ case sw::FORMAT_R32F:
+ case sw::FORMAT_G32R32F:
+ case sw::FORMAT_B32G32R32F:
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;
+ case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10:
return 10;
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8:
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;
case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5:
@@ -1048,16 +1224,43 @@
{
switch(colorFormat)
{
+ case sw::FORMAT_G16R16F:
+ case sw::FORMAT_B16G16R16F:
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;
+ case sw::FORMAT_G32R32F:
+ case sw::FORMAT_B32G32R32F:
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;
+ case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10:
return 10;
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8:
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;
case sw::FORMAT_A1R5G5B5:
return 5;
@@ -1072,16 +1275,33 @@
{
switch(colorFormat)
{
+ case sw::FORMAT_B16G16R16F:
case sw::FORMAT_A16B16G16R16F:
+ case sw::FORMAT_X16B16G16R16I:
+ case sw::FORMAT_A16B16G16R16I:
+ case sw::FORMAT_X16B16G16R16UI:
+ case sw::FORMAT_A16B16G16R16UI:
return 16;
+ case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F:
+ case sw::FORMAT_X32B32G32R32I:
+ case sw::FORMAT_A32B32G32R32I:
+ case sw::FORMAT_X32B32G32R32UI:
+ case sw::FORMAT_A32B32G32R32UI:
return 32;
+ case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10:
return 10;
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
case sw::FORMAT_X8R8G8B8:
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;
case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5:
@@ -1134,9 +1354,44 @@
case GL_COLOR_ATTACHMENT15:
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_R32F:
+ case sw::FORMAT_G32R32F:
+ case sw::FORMAT_B32G32R32F:
case sw::FORMAT_A32B32G32R32F:
return GL_FLOAT;
+ case sw::FORMAT_R8:
+ case sw::FORMAT_G8R8:
+ case sw::FORMAT_A2B10G10R10:
case sw::FORMAT_A2R10G10B10:
case sw::FORMAT_A8R8G8B8:
case sw::FORMAT_A8B8G8R8:
@@ -1145,6 +1400,11 @@
case sw::FORMAT_A1R5G5B5:
case sw::FORMAT_R5G6B5:
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:
UNREACHABLE(format);
return 0;
diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index cc1a1d1..7354f95 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -42,6 +42,7 @@
bool IsCompressed(GLenum format, egl::GLint clientVersion);
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 IsStencilTexture(GLenum format);
bool IsCubemapTextureTarget(GLenum target);
@@ -49,7 +50,7 @@
bool IsTextureTarget(GLenum target);
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 IsStencilRenderable(GLenum internalformat);