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);