Refactor read pixel format/type validation.

Bug swiftshader:38

Change-Id: I74c642b3c7346541d042acde78aa2e0213beb5f6
Reviewed-on: https://swiftshader-review.googlesource.com/9028
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 70ff932..f3c190d 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -16,6 +16,7 @@
 
 #include "utilities.h"
 
+#include "Framebuffer.h"
 #include "main.h"
 #include "mathutil.h"
 #include "Context.h"
@@ -596,82 +597,107 @@
 		return GL_NONE;
 	}
 
-	bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, GLint clientVersion)
+	bool IsValidReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type, GLint clientVersion)
 	{
-		switch(format)
+		// GL_NV_read_depth
+		if(format == GL_DEPTH_COMPONENT)
 		{
-		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)
+			Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
+
+			if(!depthbuffer)
 			{
 				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);
-		case GL_DEPTH_COMPONENT:
-			if(internalFormat != format)
-			{
-				return false;
-			}
+
 			switch(type)
 			{
 			case GL_UNSIGNED_SHORT:
 			case GL_FLOAT:
-				if(internalType != type)
-				{
-					return false;
-				}
-				break;
+				return true;
 			default:
+				UNIMPLEMENTED();
 				return false;
 			}
-			break;
-		default:
+		}
+
+		Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+
+		if(!colorbuffer)
+		{
 			return false;
 		}
-		return true;
+
+		sw::Format internalformat = colorbuffer->getInternalFormat();
+
+		if(sw::Surface::isNormalizedInteger(internalformat))
+		{
+			// Combination always supported by normalized fixed-point rendering surfaces.
+			if(format == GL_RGBA && type == GL_UNSIGNED_BYTE)
+			{
+				return true;
+			}
+		}
+		else if(sw::Surface::isFloatFormat(internalformat))
+		{
+			// Combination always supported by floating-point rendering surfaces.
+			// Supported in OpenGL ES 2.0 due to GL_EXT_color_buffer_half_float.
+			if(format == GL_RGBA && type == GL_FLOAT)
+			{
+				return true;
+			}
+		}
+		else if(sw::Surface::isSignedNonNormalizedInteger(internalformat))
+		{
+			ASSERT(clientVersion >= 3);
+
+			if(format == GL_RGBA_INTEGER && type == GL_INT)
+			{
+				return true;
+			}
+		}
+		else if(sw::Surface::isUnsignedNonNormalizedInteger(internalformat))
+		{
+			ASSERT(clientVersion >= 3);
+
+			if(format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT)
+			{
+				return true;
+			}
+		}
+		else UNREACHABLE(internalformat);
+
+		// GL_IMPLEMENTATION_COLOR_READ_FORMAT / GL_IMPLEMENTATION_COLOR_READ_TYPE
+		GLenum implementationReadFormat = GL_NONE;
+		GLenum implementationReadType = GL_NONE;
+		switch(format)
+		{
+		default:
+			implementationReadFormat = framebuffer->getImplementationColorReadFormat();
+			implementationReadType = framebuffer->getImplementationColorReadType();
+			break;
+		case GL_DEPTH_COMPONENT:
+			implementationReadFormat = framebuffer->getDepthReadFormat();
+			implementationReadType = framebuffer->getDepthReadType();
+			break;
+		}
+
+		if(format == implementationReadFormat && type == implementationReadType)
+		{
+			return true;
+		}
+
+		// Additional third combination accepted by OpenGL ES 3.0.
+		if(internalformat == sw::FORMAT_A2B10G10R10)
+		{
+			ASSERT(clientVersion >= 3);
+
+			if(format == GL_RGBA && type == GL_UNSIGNED_INT_2_10_10_10_REV)
+			{
+				return true;
+			}
+		}
+
+		return false;
 	}
 
 	bool IsDepthTexture(GLenum format)
@@ -1878,7 +1904,7 @@
 				return GL_SIGNED_NORMALIZED;
 			default:
 				UNREACHABLE(format);
-				return 0;
+				return GL_NONE;
 			}
 		case GL_DEPTH_ATTACHMENT:
 		case GL_STENCIL_ATTACHMENT:
@@ -1886,7 +1912,7 @@
 			return GL_FLOAT;
 		default:
 			UNREACHABLE(attachment);
-			return 0;
+			return GL_NONE;
 		}
 	}