Fix floating-point color buffer support.

- Implemented GL_EXT_color_buffer_float.
- Removed duplicate glRenderbufferStorageMultisample implementation.
- Refactored internalformat validation.
- Removed GL_R11F_G11F_B10F as renderable format. OpenGL ES 3.0 only supports
  this as a texture format.

Change-Id: I83ce8225c1b310006f5ce983349ea8cb8b2f7c29
Reviewed-on: https://swiftshader-review.googlesource.com/9048
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 0ebc9ed..0504a31 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -41,6 +41,7 @@
 #include <EGL/eglext.h>
 
 #include <algorithm>
+#include <string>
 
 namespace es2
 {
@@ -4254,84 +4255,90 @@
 	return device;
 }
 
-const GLubyte* Context::getExtensions(GLuint index, GLuint* numExt) const
+const GLubyte *Context::getExtensions(GLuint index, GLuint *numExt) const
 {
 	// Keep list sorted in following order:
 	// OES extensions
 	// EXT extensions
 	// Vendor extensions
-	static const GLubyte* extensions[] = {
-		(const GLubyte*)"GL_OES_compressed_ETC1_RGB8_texture",
-		(const GLubyte*)"GL_OES_depth24",
-		(const GLubyte*)"GL_OES_depth32",
-		(const GLubyte*)"GL_OES_depth_texture",
-		(const GLubyte*)"GL_OES_depth_texture_cube_map",
-		(const GLubyte*)"GL_OES_EGL_image",
-		(const GLubyte*)"GL_OES_EGL_image_external",
-		(const GLubyte*)"GL_OES_EGL_sync",
-		(const GLubyte*)"GL_OES_element_index_uint",
-		(const GLubyte*)"GL_OES_framebuffer_object",
-		(const GLubyte*)"GL_OES_packed_depth_stencil",
-		(const GLubyte*)"GL_OES_rgb8_rgba8",
-		(const GLubyte*)"GL_OES_standard_derivatives",
-		(const GLubyte*)"GL_OES_texture_float",
-		(const GLubyte*)"GL_OES_texture_float_linear",
-		(const GLubyte*)"GL_OES_texture_half_float",
-		(const GLubyte*)"GL_OES_texture_half_float_linear",
-		(const GLubyte*)"GL_OES_texture_npot",
-		(const GLubyte*)"GL_OES_texture_3D",
-		(const GLubyte*)"GL_EXT_blend_minmax",
-		(const GLubyte*)"GL_EXT_color_buffer_half_float",
-		(const GLubyte*)"GL_EXT_draw_buffers",
-		(const GLubyte*)"GL_EXT_occlusion_query_boolean",
-		(const GLubyte*)"GL_EXT_read_format_bgra",
+	static const char *es2extensions[] =
+	{
+		"GL_OES_compressed_ETC1_RGB8_texture",
+		"GL_OES_depth24",
+		"GL_OES_depth32",
+		"GL_OES_depth_texture",
+		"GL_OES_depth_texture_cube_map",
+		"GL_OES_EGL_image",
+		"GL_OES_EGL_image_external",
+		"GL_OES_EGL_sync",
+		"GL_OES_element_index_uint",
+		"GL_OES_framebuffer_object",
+		"GL_OES_packed_depth_stencil",
+		"GL_OES_rgb8_rgba8",
+		"GL_OES_standard_derivatives",
+		"GL_OES_texture_float",
+		"GL_OES_texture_float_linear",
+		"GL_OES_texture_half_float",
+		"GL_OES_texture_half_float_linear",
+		"GL_OES_texture_npot",
+		"GL_OES_texture_3D",
+		"GL_EXT_blend_minmax",
+		"GL_EXT_color_buffer_half_float",
+		"GL_EXT_draw_buffers",
+		"GL_EXT_instanced_arrays",
+		"GL_EXT_occlusion_query_boolean",
+		"GL_EXT_read_format_bgra",
 #if (S3TC_SUPPORT)
-		(const GLubyte*)"GL_EXT_texture_compression_dxt1",
+		"GL_EXT_texture_compression_dxt1",
 #endif
-		(const GLubyte*)"GL_EXT_texture_filter_anisotropic",
-		(const GLubyte*)"GL_EXT_texture_format_BGRA8888",
-		(const GLubyte*)"GL_ANGLE_framebuffer_blit",
-		(const GLubyte*)"GL_NV_framebuffer_blit",
-		(const GLubyte*)"GL_ANGLE_framebuffer_multisample",
+		"GL_EXT_texture_filter_anisotropic",
+		"GL_EXT_texture_format_BGRA8888",
+		"GL_ANGLE_framebuffer_blit",
+		"GL_ANGLE_framebuffer_multisample",
+		"GL_ANGLE_instanced_arrays",
 #if (S3TC_SUPPORT)
-		(const GLubyte*)"GL_ANGLE_texture_compression_dxt3",
-		(const GLubyte*)"GL_ANGLE_texture_compression_dxt5",
+		"GL_ANGLE_texture_compression_dxt3",
+		"GL_ANGLE_texture_compression_dxt5",
 #endif
-		(const GLubyte*)"GL_NV_fence",
-		(const GLubyte*)"GL_NV_read_depth",
-		(const GLubyte*)"GL_EXT_instanced_arrays",
-		(const GLubyte*)"GL_ANGLE_instanced_arrays",
+		"GL_NV_fence",
+		"GL_NV_framebuffer_blit",
+		"GL_NV_read_depth",
 	};
-	static const GLuint numExtensions = sizeof(extensions) / sizeof(*extensions);
+
+	// Extensions exclusive to OpenGL ES 3.0 and above.
+	static const char *es3extensions[] =
+	{
+		"GL_EXT_color_buffer_float",
+	};
+
+	GLuint numES2extensions = sizeof(es2extensions) / sizeof(es2extensions[0]);
+	GLuint numExtensions = numES2extensions;
+
+	if(clientVersion >= 3)
+	{
+		numExtensions += sizeof(es3extensions) / sizeof(es3extensions[0]);
+	}
 
 	if(numExt)
 	{
 		*numExt = numExtensions;
+
 		return nullptr;
 	}
 
 	if(index == GL_INVALID_INDEX)
 	{
-		static GLubyte* extensionsCat = nullptr;
-		if(!extensionsCat && (numExtensions > 0))
+		static std::string extensionsCat;
+
+		if(extensionsCat.empty() && (numExtensions > 0))
 		{
-			size_t totalLength = numExtensions; // 1 space between each extension name + terminating null
-			for(unsigned int i = 0; i < numExtensions; i++)
+			for(const char *extension : es2extensions)
 			{
-				totalLength += strlen(reinterpret_cast<const char*>(extensions[i]));
-			}
-			extensionsCat = new GLubyte[totalLength];
-			extensionsCat[0] = '\0';
-			for(unsigned int i = 0; i < numExtensions; i++)
-			{
-				if(i != 0)
-				{
-					strcat(reinterpret_cast<char*>(extensionsCat), " ");
-				}
-				strcat(reinterpret_cast<char*>(extensionsCat), reinterpret_cast<const char*>(extensions[i]));
+				extensionsCat += std::string(extension) + " ";
 			}
 		}
-		return extensionsCat;
+
+		return (const GLubyte*)extensionsCat.c_str();
 	}
 
 	if(index >= numExtensions)
@@ -4339,7 +4346,14 @@
 		return nullptr;
 	}
 
-	return extensions[index];
+	if(index < numES2extensions)
+	{
+		return (const GLubyte*)es2extensions[index];
+	}
+	else
+	{
+		return (const GLubyte*)es3extensions[index - numES2extensions];
+	}
 }
 
 }
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 6412ffb..3a7431a 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -697,7 +697,7 @@
 
 	Device *getDevice();
 
-	const GLubyte* getExtensions(GLuint index, GLuint* numExt = nullptr) const;
+	const GLubyte *getExtensions(GLuint index, GLuint *numExt = nullptr) const;
 
 private:
 	virtual ~Context();
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index 6227577..fa01ff3 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -328,7 +328,7 @@
 
 			if(IsRenderbuffer(mColorbufferType[i]))
 			{
-				if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
+				if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion(), false))
 				{
 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 				}
@@ -337,7 +337,7 @@
 			{
 				GLenum format = colorbuffer->getFormat();
 
-				if(!IsColorRenderable(format, egl::getClientVersion()))
+				if(!IsColorRenderable(format, egl::getClientVersion(), true))
 				{
 					return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 				}
@@ -386,7 +386,7 @@
 
 		if(IsRenderbuffer(mDepthbufferType))
 		{
-			if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
+			if(!es2::IsDepthRenderable(depthbuffer->getFormat(), egl::getClientVersion()))
 			{
 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 			}
@@ -436,7 +436,7 @@
 
 		if(IsRenderbuffer(mStencilbufferType))
 		{
-			if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
+			if(!es2::IsStencilRenderable(stencilbuffer->getFormat(), egl::getClientVersion()))
 			{
 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 			}
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 447d800..ab9fa7e 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -4662,7 +4662,7 @@
 	es2::Shader::releaseCompiler();
 }
 
-void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 {
 	TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
 	      target, samples, internalformat, width, height);
@@ -4698,84 +4698,35 @@
 		}
 
 		GLint clientVersion = context->getClientVersion();
-		switch(internalformat)
+
+		if(IsColorRenderable(internalformat, clientVersion, false))
 		{
-		case GL_DEPTH_COMPONENT32F:
-			if(clientVersion < 3)
-			{
-				return error(GL_INVALID_ENUM);
-			}
-			// fall through
-		case GL_DEPTH_COMPONENT16:
-		case GL_DEPTH_COMPONENT24:
-		case GL_DEPTH_COMPONENT32_OES:
-			context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
-			break;
-		case GL_R8:
-		case GL_R8UI:
-		case GL_R8I:
-		case GL_R16UI:
-		case GL_R16I:
-		case GL_R32UI:
-		case GL_R32I:
-		case GL_RG8:
-		case GL_RG8UI:
-		case GL_RG8I:
-		case GL_RG16UI:
-		case GL_RG16I:
-		case GL_RG32UI:
-		case GL_RG32I:
-		case GL_SRGB8_ALPHA8:
-		case GL_RGB10_A2:
-		case GL_RGBA8UI:
-		case GL_RGBA8I:
-		case GL_RGB10_A2UI:
-		case GL_RGBA16UI:
-		case GL_RGBA16I:
-		case GL_RGBA32I:
-		case GL_RGBA32UI:
-		case GL_R11F_G11F_B10F:
-		case GL_R32F:
-		case GL_RG32F:
-		case GL_RGB32F:
-		case GL_RGBA32F:
-			if(clientVersion < 3)
-			{
-				return error(GL_INVALID_ENUM);
-			}
-			// fall through
-		case GL_RGBA4:
-		case GL_RGB5_A1:
-		case GL_RGB565:
-		case GL_RGB8_OES:
-		case GL_RGBA8_OES:
-		case GL_R16F:
-		case GL_RG16F:
-		case GL_RGB16F:
-		case GL_RGBA16F:
 			context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
-			break;
-		case GL_STENCIL_INDEX8:
-			context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
-			break;
-		case GL_DEPTH32F_STENCIL8:
-			if(clientVersion < 3)
-			{
-				return error(GL_INVALID_ENUM);
-			}
-			// fall through
-		case GL_DEPTH24_STENCIL8_OES:
-			context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
-			break;
-		default:
-			return error(GL_INVALID_ENUM);
 		}
+		else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
+		{
+			context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
+		}
+		else if(IsDepthRenderable(internalformat, clientVersion))
+		{
+			context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
+		}
+		else if(IsStencilRenderable(internalformat, clientVersion))
+		{
+			context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
+		}
+		else error(GL_INVALID_ENUM);
 	}
 }
 
+void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+	RenderbufferStorageMultisample(target, samples, internalformat, width, height);
+}
+
 void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
 {
-	glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
+	RenderbufferStorageMultisample(target, 0, internalformat, width, height);
 }
 
 void SampleCoverage(GLclampf value, GLboolean invert)
diff --git a/src/OpenGL/libGLESv2/libGLESv2.hpp b/src/OpenGL/libGLESv2/libGLESv2.hpp
index 7b0354e..89811c3 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.hpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.hpp
@@ -159,6 +159,7 @@
 	                         GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
 	void (*glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
 	void (*glReleaseShaderCompiler)(void);
+	void (*glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 	void (*glRenderbufferStorageMultisampleANGLE)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 	void (*glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
 	void (*glSampleCoverage)(GLclampf value, GLboolean invert);
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index bba2179..be814f3 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -1450,103 +1450,6 @@
 	}
 }
 
-GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
-{
-	TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
-	      target, samples, internalformat, width, height);
-
-	switch(target)
-	{
-	case GL_RENDERBUFFER:
-		break;
-	default:
-		return error(GL_INVALID_ENUM);
-	}
-
-	if(width < 0 || height < 0 || samples < 0)
-	{
-		return error(GL_INVALID_VALUE);
-	}
-
-	es2::Context *context = es2::getContext();
-
-	if(context)
-	{
-		if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
-		   height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
-		   samples > es2::IMPLEMENTATION_MAX_SAMPLES)
-		{
-			return error(GL_INVALID_VALUE);
-		}
-
-		GLuint handle = context->getRenderbufferName();
-		if(handle == 0)
-		{
-			return error(GL_INVALID_OPERATION);
-		}
-
-		switch(internalformat)
-		{
-		case GL_DEPTH_COMPONENT16:
-		case GL_DEPTH_COMPONENT24:
-		case GL_DEPTH_COMPONENT32_OES:
-		case GL_DEPTH_COMPONENT32F:
-			context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
-			break;
-		case GL_R8UI:
-		case GL_R8I:
-		case GL_R16UI:
-		case GL_R16I:
-		case GL_R32UI:
-		case GL_R32I:
-		case GL_RG8UI:
-		case GL_RG8I:
-		case GL_RG16UI:
-		case GL_RG16I:
-		case GL_RG32UI:
-		case GL_RG32I:
-		case GL_RGB8UI:
-		case GL_RGB8I:
-		case GL_RGB16UI:
-		case GL_RGB16I:
-		case GL_RGB32UI:
-		case GL_RGB32I:
-		case GL_RGBA8UI:
-		case GL_RGBA8I:
-		case GL_RGB10_A2UI:
-		case GL_RGBA16UI:
-		case GL_RGBA16I:
-		case GL_RGBA32UI:
-		case GL_RGBA32I:
-			if(samples > 0)
-			{
-				return error(GL_INVALID_OPERATION);
-			}
-		case GL_RGBA4:
-		case GL_RGB5_A1:
-		case GL_RGB565:
-		case GL_SRGB8_ALPHA8:
-		case GL_RGB10_A2:
-		case GL_R8:
-		case GL_RG8:
-		case GL_RGB8:
-		case GL_RGBA8:
-			context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
-			break;
-		case GL_STENCIL_INDEX8:
-			context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
-			break;
-		case GL_DEPTH24_STENCIL8:
-		case GL_DEPTH32F_STENCIL8:
-			context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
-			break;
-
-		default:
-			return error(GL_INVALID_ENUM);
-		}
-	}
-}
-
 GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
 {
 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",
@@ -3994,7 +3897,9 @@
 		return;
 	}
 
-	if(!IsColorRenderable(internalformat, egl::getClientVersion()) && !IsDepthRenderable(internalformat) && !IsStencilRenderable(internalformat))
+	if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) &&
+	   !IsDepthRenderable(internalformat, egl::getClientVersion()) &&
+	   !IsStencilRenderable(internalformat, egl::getClientVersion()))
 	{
 		return error(GL_INVALID_ENUM);
 	}
diff --git a/src/OpenGL/libGLESv2/main.cpp b/src/OpenGL/libGLESv2/main.cpp
index 9775eaf..28efe8c 100644
--- a/src/OpenGL/libGLESv2/main.cpp
+++ b/src/OpenGL/libGLESv2/main.cpp
@@ -269,6 +269,7 @@
                     GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
 void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
 void ReleaseShaderCompiler(void);
+void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
 void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
 void SampleCoverage(GLclampf value, GLboolean invert);
@@ -1007,6 +1008,11 @@
 	return es2::ReleaseShaderCompiler();
 }
 
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+	return es2::RenderbufferStorageMultisample(target, samples, internalformat, width, height);
+}
+
 GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 {
 	return es2::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
@@ -1456,6 +1462,7 @@
 	this->glReadnPixelsEXT = es2::ReadnPixelsEXT;
 	this->glReadPixels = es2::ReadPixels;
 	this->glReleaseShaderCompiler = es2::ReleaseShaderCompiler;
+	this->glRenderbufferStorageMultisample = es2::RenderbufferStorageMultisample;
 	this->glRenderbufferStorageMultisampleANGLE = es2::RenderbufferStorageMultisampleANGLE;
 	this->glRenderbufferStorage = es2::RenderbufferStorage;
 	this->glSampleCoverage = es2::SampleCoverage;
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 8452dae..d45702c 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -1038,12 +1038,13 @@
 		return true;
 	}
 
-	bool IsColorRenderable(GLenum internalformat, GLint clientVersion)
+	bool IsColorRenderable(GLenum internalformat, GLint clientVersion, bool isTexture)
 	{
 		switch(internalformat)
 		{
 		case GL_RGB:
 		case GL_RGBA:
+			return isTexture;
 		case GL_RGBA4:
 		case GL_RGB5_A1:
 		case GL_RGB565:
@@ -1053,6 +1054,10 @@
 		case GL_RG16F:
 		case GL_RGB16F:
 		case GL_RGBA16F:
+		case GL_R32F:
+		case GL_RG32F:
+		case GL_RGB32F:
+		case GL_RGBA32F:
 		case GL_BGRA8_EXT:
 			return true;
 		case GL_R8:
@@ -1078,11 +1083,6 @@
 		case GL_RGBA16I:
 		case GL_RGBA32I:
 		case GL_RGBA32UI:
-		case GL_R11F_G11F_B10F:
-		case GL_R32F:
-		case GL_RG32F:
-		case GL_RGB32F:
-		case GL_RGBA32F:
 			return clientVersion >= 3;
 		case GL_DEPTH_COMPONENT24:
 		case GL_DEPTH_COMPONENT32_OES:
@@ -1099,17 +1099,18 @@
 		return false;
 	}
 
-	bool IsDepthRenderable(GLenum internalformat)
+	bool IsDepthRenderable(GLenum internalformat, GLint clientVersion)
 	{
 		switch(internalformat)
 		{
 		case GL_DEPTH_COMPONENT24:
-		case GL_DEPTH_COMPONENT32_OES:
-		case GL_DEPTH_COMPONENT32F:
-		case GL_DEPTH32F_STENCIL8:
 		case GL_DEPTH_COMPONENT16:
-		case GL_DEPTH24_STENCIL8_OES:
+		case GL_DEPTH24_STENCIL8_OES:    // GL_OES_packed_depth_stencil
+		case GL_DEPTH_COMPONENT32_OES:   // GL_OES_depth32
 			return true;
+		case GL_DEPTH32F_STENCIL8:
+		case GL_DEPTH_COMPONENT32F:
+			return clientVersion >= 3;
 		case GL_STENCIL_INDEX8:
 		case GL_R8:
 		case GL_R8UI:
@@ -1158,14 +1159,15 @@
 		return false;
 	}
 
-	bool IsStencilRenderable(GLenum internalformat)
+	bool IsStencilRenderable(GLenum internalformat, GLint clientVersion)
 	{
 		switch(internalformat)
 		{
-		case GL_DEPTH32F_STENCIL8:
 		case GL_STENCIL_INDEX8:
 		case GL_DEPTH24_STENCIL8_OES:
 			return true;
+		case GL_DEPTH32F_STENCIL8:
+			return clientVersion >= 3;
 		case GL_R8:
 		case GL_R8UI:
 		case GL_R8I:
diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index befdd3d..53deb98 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -55,9 +55,9 @@
 	bool IsTextureTarget(GLenum target);
 	bool ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion);
 
-	bool IsColorRenderable(GLenum internalformat, GLint clientVersion);
-	bool IsDepthRenderable(GLenum internalformat);
-	bool IsStencilRenderable(GLenum internalformat);
+	bool IsColorRenderable(GLenum internalformat, GLint clientVersion, bool isTexture);
+	bool IsDepthRenderable(GLenum internalformat, GLint clientVersion);
+	bool IsStencilRenderable(GLenum internalformat, GLint clientVersion);
 
 	// Parse the base uniform name and array index.  Returns the base name of the uniform. outSubscript is
 	// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 1c698a3..7d75217 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -2731,6 +2731,10 @@
 		case FORMAT_A32B32G32R32I:
 		case FORMAT_A32B32G32R32UI:
 			return false;
+		case FORMAT_R16F:
+		case FORMAT_G16R16F:
+		case FORMAT_B16G16R16F:
+		case FORMAT_A16B16G16R16F:
 		case FORMAT_R32F:
 		case FORMAT_G32R32F:
 		case FORMAT_B32G32R32F:
diff --git a/src/Shader/PixelRoutine.cpp b/src/Shader/PixelRoutine.cpp
index d0650b0..16e4692 100644
--- a/src/Shader/PixelRoutine.cpp
+++ b/src/Shader/PixelRoutine.cpp
@@ -2543,7 +2543,7 @@
 			}
 
 			{
-				value = (state.targetFormat[index] == FORMAT_X32B32G32R32F) ? Float4(1.0f) : *Pointer<Float4>(buffer + 16, 16);
+				value = *Pointer<Float4>(buffer + 16, 16);
 
 				if(rgbaWriteMask != 0x0000000F)
 				{