Texture Rectangle implementation

This adds support for GL_ARB_texture_rectangle, as it is used in Chromium.
This is required in order to use EGL/GLES on MacOS using IOSurface,
in order to be able to run Chromium on top of SwiftShader on MacOS.

Change-Id: I3c0b6a137892583bbfbc68149874d5bec3026b4a
Reviewed-on: https://swiftshader-review.googlesource.com/16368
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 056ef53..0a880ad 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -3937,41 +3937,42 @@
 		switch(target)
 		{
 		case GL_TEXTURE_2D:
+		case GL_TEXTURE_RECTANGLE_ARB:
+		{
+			es2::Texture2D *texture = context->getTexture2D(target);
+			if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
 			{
-				es2::Texture2D *texture = context->getTexture2D();
-				if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+				return error(GL_INVALID_OPERATION);
+			}
 
 				for(int level = 0; level < levels; level++)
-				{
+			{
 					texture->setImage(context, level, width, height, sizedInternalFormat, sizedInternalFormat, type, context->getUnpackInfo(), nullptr);
-					width = std::max(1, (width / 2));
-					height = std::max(1, (height / 2));
-				}
-				texture->makeImmutable(levels);
+				width = std::max(1, (width / 2));
+				height = std::max(1, (height / 2));
 			}
+			texture->makeImmutable(levels);
+		}
 			break;
 		case GL_TEXTURE_CUBE_MAP:
+		{
+			es2::TextureCubeMap *texture = context->getTextureCubeMap();
+			if(!texture || texture->name == 0 || texture->getImmutableFormat())
 			{
-				es2::TextureCubeMap *texture = context->getTextureCubeMap();
-				if(!texture || texture->name == 0 || texture->getImmutableFormat())
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+				return error(GL_INVALID_OPERATION);
+			}
 
 				for(int level = 0; level < levels; level++)
-				{
+			{
 					for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
-					{
+				{
 						texture->setImage(context, face, level, width, height, sizedInternalFormat, sizedInternalFormat, type, context->getUnpackInfo(), nullptr);
-					}
-					width = std::max(1, (width / 2));
-					height = std::max(1, (height / 2));
 				}
-				texture->makeImmutable(levels);
+				width = std::max(1, (width / 2));
+				height = std::max(1, (height / 2));
 			}
+			texture->makeImmutable(levels);
+		}
 			break;
 		default:
 			return error(GL_INVALID_ENUM);
@@ -4003,52 +4004,52 @@
 		switch(target)
 		{
 		case GL_TEXTURE_3D:
+		{
+			if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1))
 			{
-				if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1))
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+				return error(GL_INVALID_OPERATION);
+			}
 
-				es2::Texture3D *texture = context->getTexture3D();
-				if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+			es2::Texture3D *texture = context->getTexture3D();
+			if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
+			{
+				return error(GL_INVALID_OPERATION);
+			}
 
 				for(int level = 0; level < levels; level++)
-				{
+			{
 					texture->setImage(context, level, width, height, depth, sizedInternalFormat, sizedInternalFormat, type, context->getUnpackInfo(), nullptr);
-					width = std::max(1, (width / 2));
-					height = std::max(1, (height / 2));
-					depth = std::max(1, (depth / 2));
-				}
-				texture->makeImmutable(levels);
+				width = std::max(1, (width / 2));
+				height = std::max(1, (height / 2));
+				depth = std::max(1, (depth / 2));
 			}
+			texture->makeImmutable(levels);
+		}
 			break;
 		case GL_TEXTURE_2D_ARRAY:
+		{
+			if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
 			{
-				if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+				return error(GL_INVALID_OPERATION);
+			}
 
-				es2::Texture3D *texture = context->getTexture2DArray();
-				if(!texture || texture->name == 0 || texture->getImmutableFormat())
-				{
-					return error(GL_INVALID_OPERATION);
-				}
+			es2::Texture3D *texture = context->getTexture2DArray();
+			if(!texture || texture->name == 0 || texture->getImmutableFormat())
+			{
+				return error(GL_INVALID_OPERATION);
+			}
 
 				for(int level = 0; level < levels; level++)
-				{
+			{
 					for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
-					{
+				{
 						texture->setImage(context, level, width, height, depth, sizedInternalFormat, sizedInternalFormat, type, context->getUnpackInfo(), nullptr);
-					}
-					width = std::max(1, (width / 2));
-					height = std::max(1, (height / 2));
 				}
-				texture->makeImmutable(levels);
+				width = std::max(1, (width / 2));
+				height = std::max(1, (height / 2));
 			}
+			texture->makeImmutable(levels);
+		}
 			break;
 		default:
 			return error(GL_INVALID_ENUM);