Apply the Apache 2.0 license.

Change-Id: I4a7aeefedcd2d891093520d5a10ebefadcddb5be
Reviewed-on: https://swiftshader-review.googlesource.com/5320
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index ffcad31..09e5975 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -1,1931 +1,1934 @@
-// SwiftShader Software Renderer

-//

-// Copyright(c) 2005-2013 TransGaming Inc.

-//

-// All rights reserved. No part of this software may be copied, distributed, transmitted,

-// transcribed, stored in a retrieval system, translated into any human or computer

-// language by any means, or disclosed to third parties without the explicit written

-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express

-// or implied, including but not limited to any patent rights, are granted to you.

-//

-

-// utilities.cpp: Conversion functions and other utility routines.

-

-#include "utilities.h"

-

-#include "main.h"

-#include "mathutil.h"

-#include "Context.h"

-#include "common/debug.h"

-

-#include <limits>

-#include <stdio.h>

-#include <stdlib.h>

-

-namespace es2

-{

-	// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation

-	// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid

-	// format and type combinations.

-

-	typedef std::pair<GLenum, GLenum> FormatTypePair;

-	typedef std::pair<FormatTypePair, GLenum> FormatPair;

-	typedef std::map<FormatTypePair, GLenum> FormatMap;

-

-	// A helper function to insert data into the format map with fewer characters.

-	static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat)

-	{

-		map->insert(FormatPair(FormatTypePair(format, type), internalFormat));

-	}

-

-	FormatMap BuildFormatMap()

-	{

-		static const GLenum GL_BGRA4_ANGLEX = 0x6ABC;

-		static const GLenum GL_BGR5_A1_ANGLEX = 0x6ABD;

-

-		FormatMap map;

-

-		//                       | Format | Type | Internal format |

-		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8);

-		InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM);

-		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4);

-		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1);

-		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2);

-		InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F);

-		InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F);

-		InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F);

-

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I);

-		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI);

-

-		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8);

-		InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM);

-		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565);

-		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F);

-		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5);

-		InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F);

-		InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F);

-		InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F);

-

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI);

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I);

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI);

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I);

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI);

-		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I);

-

-		InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8);

-		InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM);

-		InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F);

-		InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F);

-		InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F);

-

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI);

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I);

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI);

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I);

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI);

-		InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I);

-

-		InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8);

-		InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM);

-		InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F);

-		InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F);

-		InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F);

-

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI);

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I);

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI);

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I);

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI);

-		InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I);

-

-		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT);

-		InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT);

-		InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT);

-		InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT);

-		InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT);

-		InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT);

-

-		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT);

-		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX);

-		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX);

-

-		InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8);

-		InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8);

-

-		InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);

-		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);

-		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);

-		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);

-

-		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16);

-		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES);

-		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F);

-

-		InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8);

-

-		InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8);

-		InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8);

-

-		return map;

-	}

-

-	GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)

-	{

-		switch(internalFormat)

-		{

-		case GL_ALPHA:

-		case GL_LUMINANCE:

-		case GL_LUMINANCE_ALPHA:

-		case GL_RED:

-		case GL_RG:

-		case GL_RGB:

-		case GL_RGBA:

-		case GL_RED_INTEGER:

-		case GL_RG_INTEGER:

-		case GL_RGB_INTEGER:

-		case GL_RGBA_INTEGER:

-		case GL_BGRA_EXT:

-		case GL_DEPTH_COMPONENT:

-		case GL_DEPTH_STENCIL:

-		case GL_SRGB_EXT:

-		case GL_SRGB_ALPHA_EXT:

-			{

-				static const FormatMap formatMap = BuildFormatMap();

-				FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));

-				return (iter != formatMap.end()) ? iter->second : GL_NONE;

-			}

-		default:

-			return internalFormat;

-		}

-	}

-

-	unsigned int UniformComponentCount(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_BOOL:

-		case GL_FLOAT:

-		case GL_INT:

-		case GL_UNSIGNED_INT:

-		case GL_SAMPLER_2D:

-		case GL_SAMPLER_CUBE:

-        case GL_SAMPLER_EXTERNAL_OES:

-		case GL_SAMPLER_3D_OES:

-		case GL_SAMPLER_2D_ARRAY:

-		case GL_SAMPLER_2D_SHADOW:

-		case GL_SAMPLER_CUBE_SHADOW:

-		case GL_SAMPLER_2D_ARRAY_SHADOW:

-		case GL_INT_SAMPLER_2D:

-		case GL_UNSIGNED_INT_SAMPLER_2D:

-		case GL_INT_SAMPLER_CUBE:

-		case GL_UNSIGNED_INT_SAMPLER_CUBE:

-		case GL_INT_SAMPLER_3D:

-		case GL_UNSIGNED_INT_SAMPLER_3D:

-		case GL_INT_SAMPLER_2D_ARRAY:

-		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:

-			return 1;

-		case GL_BOOL_VEC2:

-		case GL_FLOAT_VEC2:

-		case GL_INT_VEC2:

-		case GL_UNSIGNED_INT_VEC2:

-			return 2;

-		case GL_INT_VEC3:

-		case GL_UNSIGNED_INT_VEC3:

-		case GL_FLOAT_VEC3:

-		case GL_BOOL_VEC3:

-			return 3;

-		case GL_BOOL_VEC4:

-		case GL_FLOAT_VEC4:

-		case GL_INT_VEC4:

-		case GL_UNSIGNED_INT_VEC4:

-		case GL_FLOAT_MAT2:

-			return 4;

-		case GL_FLOAT_MAT2x3:

-		case GL_FLOAT_MAT3x2:

-			return 6;

-		case GL_FLOAT_MAT2x4:

-		case GL_FLOAT_MAT4x2:

-			return 8;

-		case GL_FLOAT_MAT3:

-			return 9;

-		case GL_FLOAT_MAT3x4:

-		case GL_FLOAT_MAT4x3:

-			return 12;

-		case GL_FLOAT_MAT4:

-			return 16;

-		default:

-			UNREACHABLE(type);

-		}

-

-		return 0;

-	}

-

-	GLenum UniformComponentType(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_BOOL:

-		case GL_BOOL_VEC2:

-		case GL_BOOL_VEC3:

-		case GL_BOOL_VEC4:

-			return GL_BOOL;

-		case GL_FLOAT:

-		case GL_FLOAT_VEC2:

-		case GL_FLOAT_VEC3:

-		case GL_FLOAT_VEC4:

-		case GL_FLOAT_MAT2:

-		case GL_FLOAT_MAT2x3:

-		case GL_FLOAT_MAT2x4:

-		case GL_FLOAT_MAT3:

-		case GL_FLOAT_MAT3x2:

-		case GL_FLOAT_MAT3x4:

-		case GL_FLOAT_MAT4:

-		case GL_FLOAT_MAT4x2:

-		case GL_FLOAT_MAT4x3:

-			return GL_FLOAT;

-		case GL_INT:

-		case GL_SAMPLER_2D:

-		case GL_SAMPLER_CUBE:

-		case GL_SAMPLER_EXTERNAL_OES:

-		case GL_SAMPLER_3D_OES:

-		case GL_SAMPLER_2D_ARRAY:

-		case GL_SAMPLER_2D_SHADOW:

-		case GL_SAMPLER_CUBE_SHADOW:

-		case GL_SAMPLER_2D_ARRAY_SHADOW:

-		case GL_INT_SAMPLER_2D:

-		case GL_UNSIGNED_INT_SAMPLER_2D:

-		case GL_INT_SAMPLER_CUBE:

-		case GL_UNSIGNED_INT_SAMPLER_CUBE:

-		case GL_INT_SAMPLER_3D:

-		case GL_UNSIGNED_INT_SAMPLER_3D:

-		case GL_INT_SAMPLER_2D_ARRAY:

-		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:

-		case GL_INT_VEC2:

-		case GL_INT_VEC3:

-		case GL_INT_VEC4:

-			return GL_INT;

-		case GL_UNSIGNED_INT:

-		case GL_UNSIGNED_INT_VEC2:

-		case GL_UNSIGNED_INT_VEC3:

-		case GL_UNSIGNED_INT_VEC4:

-			return GL_UNSIGNED_INT;

-		default:

-			UNREACHABLE(type);

-		}

-

-		return GL_NONE;

-	}

-

-	size_t UniformTypeSize(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_BOOL:  return sizeof(GLboolean);

-		case GL_FLOAT: return sizeof(GLfloat);

-		case GL_INT:   return sizeof(GLint);

-		case GL_UNSIGNED_INT: return sizeof(GLuint);

-		}

-

-		return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);

-	}

-

-	bool IsSamplerUniform(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_SAMPLER_2D:

-		case GL_SAMPLER_CUBE:

-		case GL_SAMPLER_EXTERNAL_OES:

-		case GL_SAMPLER_3D_OES:

-		case GL_SAMPLER_2D_ARRAY:

-		case GL_SAMPLER_2D_SHADOW:

-		case GL_SAMPLER_CUBE_SHADOW:

-		case GL_SAMPLER_2D_ARRAY_SHADOW:

-		case GL_INT_SAMPLER_2D:

-		case GL_UNSIGNED_INT_SAMPLER_2D:

-		case GL_INT_SAMPLER_CUBE:

-		case GL_UNSIGNED_INT_SAMPLER_CUBE:

-		case GL_INT_SAMPLER_3D:

-		case GL_UNSIGNED_INT_SAMPLER_3D:

-		case GL_INT_SAMPLER_2D_ARRAY:

-		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:

-			return true;

-		default:

-			return false;

-		}

-	}

-

-	int VariableRowCount(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_NONE:

-			return 0;

-		case GL_BOOL:

-		case GL_FLOAT:

-		case GL_INT:

-		case GL_UNSIGNED_INT:

-		case GL_BOOL_VEC2:

-		case GL_FLOAT_VEC2:

-		case GL_INT_VEC2:

-		case GL_UNSIGNED_INT_VEC2:

-		case GL_INT_VEC3:

-		case GL_UNSIGNED_INT_VEC3:

-		case GL_FLOAT_VEC3:

-		case GL_BOOL_VEC3:

-		case GL_BOOL_VEC4:

-		case GL_FLOAT_VEC4:

-		case GL_INT_VEC4:

-		case GL_UNSIGNED_INT_VEC4:

-		case GL_SAMPLER_2D:

-		case GL_SAMPLER_CUBE:

-        case GL_SAMPLER_EXTERNAL_OES:

-		case GL_SAMPLER_3D_OES:

-		case GL_SAMPLER_2D_ARRAY:

-		case GL_SAMPLER_2D_SHADOW:

-		case GL_SAMPLER_CUBE_SHADOW:

-		case GL_SAMPLER_2D_ARRAY_SHADOW:

-		case GL_INT_SAMPLER_2D:

-		case GL_UNSIGNED_INT_SAMPLER_2D:

-		case GL_INT_SAMPLER_CUBE:

-		case GL_UNSIGNED_INT_SAMPLER_CUBE:

-		case GL_INT_SAMPLER_3D:

-		case GL_UNSIGNED_INT_SAMPLER_3D:

-		case GL_INT_SAMPLER_2D_ARRAY:

-		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:

-			return 1;

-		case GL_FLOAT_MAT2:

-		case GL_FLOAT_MAT3x2:

-		case GL_FLOAT_MAT4x2:

-			return 2;

-		case GL_FLOAT_MAT3:

-		case GL_FLOAT_MAT2x3:

-		case GL_FLOAT_MAT4x3:

-			return 3;

-		case GL_FLOAT_MAT4:

-		case GL_FLOAT_MAT2x4:

-		case GL_FLOAT_MAT3x4:

-			return 4;

-		default:

-			UNREACHABLE(type);

-		}

-

-		return 0;

-	}

-

-	int VariableColumnCount(GLenum type)

-	{

-		switch(type)

-		{

-		case GL_NONE:

-			return 0;

-		case GL_BOOL:

-		case GL_FLOAT:

-		case GL_INT:

-		case GL_UNSIGNED_INT:

-			return 1;

-		case GL_BOOL_VEC2:

-		case GL_FLOAT_VEC2:

-		case GL_INT_VEC2:

-		case GL_UNSIGNED_INT_VEC2:

-		case GL_FLOAT_MAT2:

-		case GL_FLOAT_MAT2x3:

-		case GL_FLOAT_MAT2x4:

-			return 2;

-		case GL_INT_VEC3:

-		case GL_UNSIGNED_INT_VEC3:

-		case GL_FLOAT_VEC3:

-		case GL_BOOL_VEC3:

-		case GL_FLOAT_MAT3:

-		case GL_FLOAT_MAT3x2:

-		case GL_FLOAT_MAT3x4:

-			return 3;

-		case GL_BOOL_VEC4:

-		case GL_FLOAT_VEC4:

-		case GL_INT_VEC4:

-		case GL_UNSIGNED_INT_VEC4:

-		case GL_FLOAT_MAT4:

-		case GL_FLOAT_MAT4x2:

-		case GL_FLOAT_MAT4x3:

-			return 4;

-		default:

-			UNREACHABLE(type);

-		}

-

-		return 0;

-	}

-

-	int VariableRegisterCount(GLenum type)

-	{

-		// Number of registers used is the number of columns for matrices or 1 for scalars and vectors

-		return (VariableRowCount(type) > 1) ? VariableColumnCount(type) : 1;

-	}

-

-	int VariableRegisterSize(GLenum type)

-	{

-		// Number of components per register is the number of rows for matrices or columns for scalars and vectors

-		int nbRows = VariableRowCount(type);

-		return (nbRows > 1) ? nbRows : VariableColumnCount(type);

-	}

-

-	int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)

-	{

-		ASSERT(allocationSize <= bitsSize);

-

-		unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);

-

-		for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)

-		{

-			if((*bits & mask) == 0)

-			{

-				*bits |= mask;

-				return i;

-			}

-

-			mask <<= 1;

-		}

-

-		return -1;

-	}

-

-	GLint floatToInt(GLfloat value)

-	{

-		return static_cast<GLint>((static_cast<GLfloat>(0xFFFFFFFF) * value - 1.0f) * 0.5f);

-	}

-

-	bool IsCompressed(GLenum format, GLint clientVersion)

-	{

-		return ValidateCompressedFormat(format, clientVersion, true) == GL_NONE;

-	}

-

-	GLenum ValidateCompressedFormat(GLenum format, GLint clientVersion, bool expectCompressedFormats)

-	{

-		switch(format)

-		{

-		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

-		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

-		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

-		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:

-			return S3TC_SUPPORT ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;

-		case GL_ETC1_RGB8_OES:

-			return expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION;

-		case GL_COMPRESSED_R11_EAC:

-		case GL_COMPRESSED_SIGNED_R11_EAC:

-		case GL_COMPRESSED_RG11_EAC:

-		case GL_COMPRESSED_SIGNED_RG11_EAC:

-		case GL_COMPRESSED_RGB8_ETC2:

-		case GL_COMPRESSED_SRGB8_ETC2:

-		case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:

-		case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:

-		case GL_COMPRESSED_RGBA8_ETC2_EAC:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:

-		case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:

-		case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:

-		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:

-			return (clientVersion >= 3) ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;

-		default:

-			return expectCompressedFormats ? GL_INVALID_ENUM : GL_NONE; // Not compressed format

-		}

-	}

-

-	GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)

-	{

-		if(!texture)

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(compressed != texture->isCompressed(target, level))

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(sizedInternalFormat != GL_NONE && sizedInternalFormat != texture->getFormat(target, level))

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(compressed)

-		{

-			if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||

-			   (height % 4 != 0 && height != texture->getHeight(target, 0)))

-			{

-				return GL_INVALID_OPERATION;

-			}

-		}

-

-		if(xoffset + width > texture->getWidth(target, level) ||

-		   yoffset + height > texture->getHeight(target, level))

-		{

-			return GL_INVALID_VALUE;

-		}

-

-		return GL_NONE;

-	}

-

-	GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)

-	{

-		if(!texture)

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(compressed != texture->isCompressed(target, level))

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(sizedInternalFormat != GL_NONE && sizedInternalFormat != GetSizedInternalFormat(texture->getFormat(target, level), texture->getType(target, level)))

-		{

-			return GL_INVALID_OPERATION;

-		}

-

-		if(compressed)

-		{

-			if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||

-			   (height % 4 != 0 && height != texture->getHeight(target, 0)) ||

-			   (depth % 4 != 0 && depth != texture->getDepth(target, 0)))

-			{

-				return GL_INVALID_OPERATION;

-			}

-		}

-

-		if(xoffset + width > texture->getWidth(target, level) ||

-		   yoffset + height > texture->getHeight(target, level) ||

-		   zoffset + depth > texture->getDepth(target, level))

-		{

-			return GL_INVALID_VALUE;

-		}

-

-		return GL_NONE;

-	}

-

-	bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, 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);

-		case GL_DEPTH_COMPONENT:

-			if (internalFormat != format)

-			{

-				return false;

-			}

-			switch(type)

-			{

-			case GL_UNSIGNED_SHORT:

-			case GL_FLOAT:

-				if (internalType != type)

-				{

-					return false;

-				}

-				break;

-			default:

-				return false;

-			}

-			break;

-		default:

-			return false;

-		}

-		return true;

-	}

-

-	bool IsDepthTexture(GLenum format)

-	{

-		return format == GL_DEPTH_COMPONENT ||

-		       format == GL_DEPTH_STENCIL_OES ||

-		       format == GL_DEPTH_COMPONENT16 ||

-		       format == GL_DEPTH_COMPONENT24 ||

-		       format == GL_DEPTH_COMPONENT32_OES ||

-		       format == GL_DEPTH_COMPONENT32F ||

-		       format == GL_DEPTH24_STENCIL8 ||

-		       format == GL_DEPTH32F_STENCIL8;

-	}

-

-	bool IsStencilTexture(GLenum format)

-	{

-		return format == GL_STENCIL_INDEX_OES ||

-		       format == GL_DEPTH_STENCIL_OES ||

-		       format == GL_DEPTH24_STENCIL8 ||

-		       format == GL_DEPTH32F_STENCIL8;

-	}

-

-	bool IsCubemapTextureTarget(GLenum target)

-	{

-		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);

-	}

-

-	int CubeFaceIndex(GLenum cubeFace)

-	{

-		switch(cubeFace)

-		{

-		case GL_TEXTURE_CUBE_MAP:

-		case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;

-		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;

-		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;

-		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;

-		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;

-		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;

-		default: UNREACHABLE(cubeFace); return 0;

-		}

-	}

-

-	bool IsTextureTarget(GLenum target)

-	{

-		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) || target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;

-	}

-

-	bool ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion)

-	{

-		switch(type)

-		{

-		case GL_UNSIGNED_BYTE:

-		case GL_UNSIGNED_SHORT_4_4_4_4:

-		case GL_UNSIGNED_SHORT_5_5_5_1:

-		case GL_UNSIGNED_SHORT_5_6_5:

-		case GL_FLOAT:               // GL_OES_texture_float

-		case GL_HALF_FLOAT_OES:      // GL_OES_texture_half_float

-		case GL_UNSIGNED_INT_24_8:   // GL_OES_packed_depth_stencil (GL_UNSIGNED_INT_24_8_EXT)

-		case GL_UNSIGNED_SHORT:      // GL_OES_depth_texture

-		case GL_UNSIGNED_INT:        // GL_OES_depth_texture

-			break;

-		case GL_BYTE:

-		case GL_SHORT:

-		case GL_INT:

-		case GL_HALF_FLOAT:

-		case GL_UNSIGNED_INT_2_10_10_10_REV:

-		case GL_UNSIGNED_INT_10F_11F_11F_REV:

-		case GL_UNSIGNED_INT_5_9_9_9_REV:

-		case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:

-			if(clientVersion < 3)

-			{

-				return error(GL_INVALID_ENUM, false);

-			}

-			break;

-		default:

-			return error(GL_INVALID_ENUM, false);

-		}

-

-		switch(format)

-		{

-		case GL_ALPHA:

-		case GL_RGB:

-		case GL_RGBA:

-		case GL_LUMINANCE:

-		case GL_LUMINANCE_ALPHA:

-		case GL_BGRA_EXT:          // GL_EXT_texture_format_BGRA8888

-		case GL_DEPTH_STENCIL:     // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES)

-		case GL_DEPTH_COMPONENT:   // GL_OES_depth_texture

-			break;

-		case GL_RED:

-		case GL_RED_INTEGER:

-		case GL_RG:

-		case GL_RG_INTEGER:

-		case GL_RGB_INTEGER:

-		case GL_RGBA_INTEGER:

-			if(clientVersion < 3)

-			{

-				return error(GL_INVALID_ENUM, false);

-			}

-			break;

-		default:

-			return error(GL_INVALID_ENUM, false);

-		}

-

-		if(internalformat != format)

-		{

-			if(clientVersion < 3)

-			{

-				return error(GL_INVALID_OPERATION, false);

-			}

-

-			switch(internalformat)

-			{

-			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_RGB8UI:

-			case GL_RGB8I:

-			case GL_RGB16UI:

-			case GL_RGB16I:

-			case GL_RGB32UI:

-			case GL_RGB32I:

-			case GL_RG8_SNORM:

-			case GL_R8_SNORM:

-			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_RGBA4:

-			case GL_RGB5_A1:

-			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_COMPONENT24:

-			case GL_DEPTH_COMPONENT32_OES:

-			case GL_DEPTH_COMPONENT32F:

-			case GL_DEPTH32F_STENCIL8:

-			case GL_DEPTH_COMPONENT16:

-			case GL_STENCIL_INDEX8:

-			case GL_DEPTH24_STENCIL8_OES:

-			case GL_RGBA8_SNORM:

-			case GL_SRGB8:

-			case GL_RGB8_SNORM:

-			case GL_RGB9_E5:

-				break;

-			default:

-				return error(GL_INVALID_ENUM, false);

-			}

-		}

-

-		// Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2]

-		bool validSizedInternalformat = false;

-		#define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break;

-

-		switch(format)

-		{

-		case GL_RGBA:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8, GL_RGB5_A1, GL_RGBA4, GL_SRGB8_ALPHA8)

-			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGBA8_SNORM)

-			case GL_HALF_FLOAT_OES:              break;

-			case GL_UNSIGNED_SHORT_4_4_4_4:      VALIDATE_INTERNALFORMAT(GL_RGBA4)

-			case GL_UNSIGNED_SHORT_5_5_5_1:      VALIDATE_INTERNALFORMAT(GL_RGB5_A1)

-			case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2, GL_RGB5_A1)

-			case GL_HALF_FLOAT:                  VALIDATE_INTERNALFORMAT(GL_RGBA16F)

-			case GL_FLOAT:                       VALIDATE_INTERNALFORMAT(GL_RGBA32F, GL_RGBA16F)

-			default:                             return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RGBA_INTEGER:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8UI)

-			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGBA8I)

-			case GL_UNSIGNED_SHORT:              VALIDATE_INTERNALFORMAT(GL_RGBA16UI)

-			case GL_SHORT:                       VALIDATE_INTERNALFORMAT(GL_RGBA16I)

-			case GL_UNSIGNED_INT:                VALIDATE_INTERNALFORMAT(GL_RGBA32UI)

-			case GL_INT:                         VALIDATE_INTERNALFORMAT(GL_RGBA32I)

-			case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2UI)

-			default:                             return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RGB:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:                VALIDATE_INTERNALFORMAT(GL_RGB8, GL_RGB565, GL_SRGB8)

-			case GL_BYTE:                         VALIDATE_INTERNALFORMAT(GL_RGB8_SNORM)

-			case GL_HALF_FLOAT_OES:               break;

-			case GL_UNSIGNED_SHORT_5_6_5:         VALIDATE_INTERNALFORMAT(GL_RGB565)

-			case GL_UNSIGNED_INT_10F_11F_11F_REV: VALIDATE_INTERNALFORMAT(GL_R11F_G11F_B10F)

-			case GL_UNSIGNED_INT_5_9_9_9_REV:     VALIDATE_INTERNALFORMAT(GL_RGB9_E5)

-			case GL_HALF_FLOAT:                   VALIDATE_INTERNALFORMAT(GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)

-			case GL_FLOAT:                        VALIDATE_INTERNALFORMAT(GL_RGB32F, GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)

-			default:                              return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RGB_INTEGER:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGB8UI)

-			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGB8I)

-			case GL_UNSIGNED_SHORT:              VALIDATE_INTERNALFORMAT(GL_RGB16UI)

-			case GL_SHORT:                       VALIDATE_INTERNALFORMAT(GL_RGB16I)

-			case GL_UNSIGNED_INT:                VALIDATE_INTERNALFORMAT(GL_RGB32UI)

-			case GL_INT:                         VALIDATE_INTERNALFORMAT(GL_RGB32I)

-			default:                             return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RG:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RG8)

-			case GL_BYTE:          VALIDATE_INTERNALFORMAT(GL_RG8_SNORM)

-			case GL_HALF_FLOAT:    VALIDATE_INTERNALFORMAT(GL_RG16F)

-			case GL_FLOAT:         VALIDATE_INTERNALFORMAT(GL_RG32F, GL_RG16F)

-			default:               return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RG_INTEGER:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_RG8UI)

-			case GL_BYTE:           VALIDATE_INTERNALFORMAT(GL_RG8I)

-			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_RG16UI)

-			case GL_SHORT:          VALIDATE_INTERNALFORMAT(GL_RG16I)

-			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_RG32UI)

-			case GL_INT:            VALIDATE_INTERNALFORMAT(GL_RG32I)

-			default:                return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RED:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_R8)

-			case GL_BYTE:          VALIDATE_INTERNALFORMAT(GL_R8_SNORM)

-			case GL_HALF_FLOAT:    VALIDATE_INTERNALFORMAT(GL_R16F)

-			case GL_FLOAT:         VALIDATE_INTERNALFORMAT(GL_R32F, GL_R16F)

-			default:               return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_RED_INTEGER:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_R8UI)

-			case GL_BYTE:           VALIDATE_INTERNALFORMAT(GL_R8I)

-			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_R16UI)

-			case GL_SHORT:          VALIDATE_INTERNALFORMAT(GL_R16I)

-			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_R32UI)

-			case GL_INT:            VALIDATE_INTERNALFORMAT(GL_R32I)

-			default:                return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_DEPTH_COMPONENT:

-			switch(type)

-			{

-			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT16)

-			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16)

-			case GL_FLOAT:          VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT32F)

-			default:                return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_DEPTH_STENCIL:

-			switch(type)

-			{

-			case GL_UNSIGNED_INT_24_8:              VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8)

-			case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: VALIDATE_INTERNALFORMAT(GL_DEPTH32F_STENCIL8)

-			default:                                return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_LUMINANCE_ALPHA:

-		case GL_LUMINANCE:

-		case GL_ALPHA:

-			switch(type)

-			{

-			case GL_UNSIGNED_BYTE:

-			case GL_HALF_FLOAT_OES:

-			case GL_FLOAT:

-				break;

-			default:

-				return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		case GL_BGRA_EXT:

-			if(type != GL_UNSIGNED_BYTE)

-			{

-				return error(GL_INVALID_OPERATION, false);

-			}

-			break;

-		default:

-			UNREACHABLE(format);

-			return error(GL_INVALID_ENUM, false);

-		}

-

-		#undef VALIDATE_INTERNALFORMAT

-

-		if(internalformat != format && !validSizedInternalformat)

-		{

-			return error(GL_INVALID_OPERATION, false);

-		}

-

-		return true;

-	}

-

-	bool IsColorRenderable(GLenum internalformat, GLint clientVersion)

-	{

-		switch(internalformat)

-		{

-		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:

-		case GL_BGRA8_EXT:

-			return true;

-		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:

-			return clientVersion >= 3;

-		case GL_DEPTH_COMPONENT24:

-		case GL_DEPTH_COMPONENT32_OES:

-		case GL_DEPTH_COMPONENT32F:

-		case GL_DEPTH32F_STENCIL8:

-		case GL_DEPTH_COMPONENT16:

-		case GL_STENCIL_INDEX8:

-		case GL_DEPTH24_STENCIL8_OES:

-			return false;

-		default:

-			UNIMPLEMENTED();

-		}

-

-		return false;

-	}

-

-	bool IsDepthRenderable(GLenum internalformat)

-	{

-		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:

-			return true;

-		case GL_STENCIL_INDEX8:

-		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_RGBA4:

-		case GL_RGB5_A1:

-		case GL_RGB565:

-		case GL_RGB8_OES:

-		case GL_RGBA8_OES:

-		case GL_RGB:

-		case GL_RGBA:

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

-		}

-

-		return false;

-	}

-

-	bool IsStencilRenderable(GLenum internalformat)

-	{

-		switch(internalformat)

-		{

-		case GL_DEPTH32F_STENCIL8:

-		case GL_STENCIL_INDEX8:

-		case GL_DEPTH24_STENCIL8_OES:

-			return true;

-		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_RGBA4:

-		case GL_RGB5_A1:

-		case GL_RGB565:

-		case GL_RGB8_OES:

-		case GL_RGBA8_OES:

-		case GL_RGB:

-		case GL_RGBA:

-		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:

-			UNIMPLEMENTED();

-		}

-

-		return false;

-	}

-

-	std::string ParseUniformName(const std::string &name, size_t *outSubscript)

-	{

-		// Strip any trailing array operator and retrieve the subscript

-		size_t open = name.find_last_of('[');

-		size_t close = name.find_last_of(']');

-		bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);

-		if(!hasIndex)

-		{

-			if(outSubscript)

-			{

-				*outSubscript = GL_INVALID_INDEX;

-			}

-			return name;

-		}

-

-		if(outSubscript)

-		{

-			int index = atoi(name.substr(open + 1).c_str());

-			if(index >= 0)

-			{

-				*outSubscript = index;

-			}

-			else

-			{

-				*outSubscript = GL_INVALID_INDEX;

-			}

-		}

-

-		return name.substr(0, open);

-	}

-}

-

-namespace es2sw

-{

-	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)

-	{

-		switch(comparison)

-		{

-		case GL_NEVER:    return sw::DEPTH_NEVER;

-		case GL_ALWAYS:   return sw::DEPTH_ALWAYS;

-		case GL_LESS:     return sw::DEPTH_LESS;

-		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL;

-		case GL_EQUAL:    return sw::DEPTH_EQUAL;

-		case GL_GREATER:  return sw::DEPTH_GREATER;

-		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL;

-		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;

-		default: UNREACHABLE(comparison);

-		}

-

-		return sw::DEPTH_ALWAYS;

-	}

-

-	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)

-	{

-		switch(comparison)

-		{

-		case GL_NEVER:    return sw::STENCIL_NEVER;

-		case GL_ALWAYS:   return sw::STENCIL_ALWAYS;

-		case GL_LESS:     return sw::STENCIL_LESS;

-		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL;

-		case GL_EQUAL:    return sw::STENCIL_EQUAL;

-		case GL_GREATER:  return sw::STENCIL_GREATER;

-		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL;

-		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;

-		default: UNREACHABLE(comparison);

-		}

-

-		return sw::STENCIL_ALWAYS;

-	}

-

-	sw::Color<float> ConvertColor(es2::Color color)

-	{

-		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);

-	}

-

-	sw::BlendFactor ConvertBlendFunc(GLenum blend)

-	{

-		switch(blend)

-		{

-		case GL_ZERO:                     return sw::BLEND_ZERO;

-		case GL_ONE:                      return sw::BLEND_ONE;

-		case GL_SRC_COLOR:                return sw::BLEND_SOURCE;

-		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE;

-		case GL_DST_COLOR:                return sw::BLEND_DEST;

-		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST;

-		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA;

-		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA;

-		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA;

-		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA;

-		case GL_CONSTANT_COLOR:           return sw::BLEND_CONSTANT;

-		case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;

-		case GL_CONSTANT_ALPHA:           return sw::BLEND_CONSTANTALPHA;

-		case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;

-		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT;

-		default: UNREACHABLE(blend);

-		}

-

-		return sw::BLEND_ZERO;

-	}

-

-	sw::BlendOperation ConvertBlendOp(GLenum blendOp)

-	{

-		switch(blendOp)

-		{

-		case GL_FUNC_ADD:              return sw::BLENDOP_ADD;

-		case GL_FUNC_SUBTRACT:         return sw::BLENDOP_SUB;

-		case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;

-		case GL_MIN_EXT:               return sw::BLENDOP_MIN;

-		case GL_MAX_EXT:               return sw::BLENDOP_MAX;

-		default: UNREACHABLE(blendOp);

-		}

-

-		return sw::BLENDOP_ADD;

-	}

-

-	sw::StencilOperation ConvertStencilOp(GLenum stencilOp)

-	{

-		switch(stencilOp)

-		{

-		case GL_ZERO:      return sw::OPERATION_ZERO;

-		case GL_KEEP:      return sw::OPERATION_KEEP;

-		case GL_REPLACE:   return sw::OPERATION_REPLACE;

-		case GL_INCR:      return sw::OPERATION_INCRSAT;

-		case GL_DECR:      return sw::OPERATION_DECRSAT;

-		case GL_INVERT:    return sw::OPERATION_INVERT;

-		case GL_INCR_WRAP: return sw::OPERATION_INCR;

-		case GL_DECR_WRAP: return sw::OPERATION_DECR;

-		default: UNREACHABLE(stencilOp);

-		}

-

-		return sw::OPERATION_KEEP;

-	}

-

-	sw::AddressingMode ConvertTextureWrap(GLenum wrap)

-	{

-		switch(wrap)

-		{

-		case GL_REPEAT:            return sw::ADDRESSING_WRAP;

-		case GL_CLAMP_TO_EDGE:     return sw::ADDRESSING_CLAMP;

-		case GL_MIRRORED_REPEAT:   return sw::ADDRESSING_MIRROR;

-		default: UNREACHABLE(wrap);

-		}

-

-		return sw::ADDRESSING_WRAP;

-	}

-

-	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType)

-	{

-		switch(swizzleType)

-		{

-		case GL_RED:   return sw::SWIZZLE_RED;

-		case GL_GREEN: return sw::SWIZZLE_GREEN;

-		case GL_BLUE:  return sw::SWIZZLE_BLUE;

-		case GL_ALPHA: return sw::SWIZZLE_ALPHA;

-		case GL_ZERO:  return sw::SWIZZLE_ZERO;

-		case GL_ONE:   return sw::SWIZZLE_ONE;

-		default: UNREACHABLE(swizzleType);

-		}

-

-		return sw::SWIZZLE_RED;

-	};

-

-	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)

-	{

-		switch(cullFace)

-		{

-		case GL_FRONT:

-			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);

-		case GL_BACK:

-			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);

-		case GL_FRONT_AND_BACK:

-			return sw::CULL_NONE;   // culling will be handled during draw

-		default: UNREACHABLE(cullFace);

-		}

-

-		return sw::CULL_COUNTERCLOCKWISE;

-	}

-

-	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)

-	{

-		return (red   ? 0x00000001 : 0) |

-			   (green ? 0x00000002 : 0) |

-			   (blue  ? 0x00000004 : 0) |

-			   (alpha ? 0x00000008 : 0);

-	}

-

-	sw::MipmapType ConvertMipMapFilter(GLenum minFilter)

-	{

-		switch(minFilter)

-		{

-		case GL_NEAREST:

-		case GL_LINEAR:

-			return sw::MIPMAP_NONE;

-			break;

-		case GL_NEAREST_MIPMAP_NEAREST:

-		case GL_LINEAR_MIPMAP_NEAREST:

-			return sw::MIPMAP_POINT;

-			break;

-		case GL_NEAREST_MIPMAP_LINEAR:

-		case GL_LINEAR_MIPMAP_LINEAR:

-			return sw::MIPMAP_LINEAR;

-			break;

-		default:

-			UNREACHABLE(minFilter);

-			return sw::MIPMAP_NONE;

-		}

-	}

-

-	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)

-	{

-		if(maxAnisotropy > 1.0f)

-		{

-			return sw::FILTER_ANISOTROPIC;

-		}

-

-		sw::FilterType magFilterType = sw::FILTER_POINT;

-		switch(magFilter)

-		{

-		case GL_NEAREST: magFilterType = sw::FILTER_POINT;  break;

-		case GL_LINEAR:  magFilterType = sw::FILTER_LINEAR; break;

-		default: UNREACHABLE(magFilter);

-		}

-

-		switch(minFilter)

-		{

-		case GL_NEAREST:

-		case GL_NEAREST_MIPMAP_NEAREST:

-		case GL_NEAREST_MIPMAP_LINEAR:

-			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;

-		case GL_LINEAR:

-		case GL_LINEAR_MIPMAP_NEAREST:

-		case GL_LINEAR_MIPMAP_LINEAR:

-			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;

-		default:

-			UNREACHABLE(minFilter);

-			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;

-		}

-	}

-

-	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType,  sw::DrawType &drawType, int &primitiveCount)

-	{

-		switch(primitiveType)

-		{

-		case GL_POINTS:

-			drawType = sw::DRAW_POINTLIST;

-			primitiveCount = elementCount;

-			break;

-		case GL_LINES:

-			drawType = sw::DRAW_LINELIST;

-			primitiveCount = elementCount / 2;

-			break;

-		case GL_LINE_LOOP:

-			drawType = sw::DRAW_LINELOOP;

-			primitiveCount = elementCount;

-			break;

-		case GL_LINE_STRIP:

-			drawType = sw::DRAW_LINESTRIP;

-			primitiveCount = elementCount - 1;

-			break;

-		case GL_TRIANGLES:

-			drawType = sw::DRAW_TRIANGLELIST;

-			primitiveCount = elementCount / 3;

-			break;

-		case GL_TRIANGLE_STRIP:

-			drawType = sw::DRAW_TRIANGLESTRIP;

-			primitiveCount = elementCount - 2;

-			break;

-		case GL_TRIANGLE_FAN:

-			drawType = sw::DRAW_TRIANGLEFAN;

-			primitiveCount = elementCount - 2;

-			break;

-		default:

-			return false;

-		}

-

-		sw::DrawType elementSize;

-		switch(elementType)

-		{

-		case GL_NONE:           elementSize = sw::DRAW_NONINDEXED; break;

-		case GL_UNSIGNED_BYTE:  elementSize = sw::DRAW_INDEXED8;   break;

-		case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16;  break;

-		case GL_UNSIGNED_INT:   elementSize = sw::DRAW_INDEXED32;  break;

-		default: return false;

-		}

-

-		drawType = sw::DrawType(drawType | elementSize);

-

-		return true;

-	}

-

-	sw::Format ConvertRenderbufferFormat(GLenum format)

-	{

-		switch(format)

-		{

-		case GL_RGBA4:

-		case GL_RGB5_A1:

-		case GL_RGBA8_OES:            return sw::FORMAT_A8B8G8R8;

-		case GL_RGB565:               return sw::FORMAT_R5G6B5;

-		case GL_RGB8_OES:             return sw::FORMAT_X8B8G8R8;

-		case GL_DEPTH_COMPONENT16:

-		case GL_STENCIL_INDEX8:

-		case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;

-		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:                return sw::FORMAT_SRGB8_X8;

-		case GL_SRGB8_ALPHA8:         return sw::FORMAT_SRGB8_A8;

-		default: UNREACHABLE(format); return sw::FORMAT_NULL;

-		}

-	}

-}

-

-namespace sw2es

-{

-	unsigned int GetStencilSize(sw::Format stencilFormat)

-	{

-		switch(stencilFormat)

-		{

-		case sw::FORMAT_D24FS8:

-		case sw::FORMAT_D24S8:

-		case sw::FORMAT_D32FS8_TEXTURE:

-		case sw::FORMAT_D32FS8_SHADOW:

-		case sw::FORMAT_S8:

-			return 8;

-	//	case sw::FORMAT_D24X4S4:

-	//		return 4;

-	//	case sw::FORMAT_D15S1:

-	//		return 1;

-	//	case sw::FORMAT_D16_LOCKABLE:

-		case sw::FORMAT_D32:

-		case sw::FORMAT_D24X8:

-		case sw::FORMAT_D32F_LOCKABLE:

-		case sw::FORMAT_D16:

-			return 0;

-	//	case sw::FORMAT_D32_LOCKABLE:  return 0;

-	//	case sw::FORMAT_S8_LOCKABLE:   return 8;

-		default:

-			return 0;

-		}

-	}

-

-	unsigned int GetAlphaSize(sw::Format colorFormat)

-	{

-		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_SRGB8_A8:

-		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:

-		case sw::FORMAT_X8B8G8R8:

-		case sw::FORMAT_SRGB8_X8:

-		case sw::FORMAT_R5G6B5:

-			return 0;

-		default:

-			return 0;

-		}

-	}

-

-	unsigned int GetRedSize(sw::Format colorFormat)

-	{

-		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_X32B32G32R32F:

-		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_SRGB8_A8:

-		case sw::FORMAT_SRGB8_X8:

-		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:

-			return 5;

-		default:

-			return 0;

-		}

-	}

-

-	unsigned int GetGreenSize(sw::Format colorFormat)

-	{

-		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_X32B32G32R32F:

-		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_SRGB8_A8:

-		case sw::FORMAT_SRGB8_X8:

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

-		case sw::FORMAT_R5G6B5:

-			return 6;

-		default:

-			return 0;

-		}

-	}

-

-	unsigned int GetBlueSize(sw::Format colorFormat)

-	{

-		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_X32B32G32R32F:

-		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_SRGB8_A8:

-		case sw::FORMAT_SRGB8_X8:

-		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:

-			return 5;

-		default:

-			return 0;

-		}

-	}

-

-	unsigned int GetDepthSize(sw::Format depthFormat)

-	{

-		switch(depthFormat)

-		{

-	//	case sw::FORMAT_D16_LOCKABLE:   return 16;

-		case sw::FORMAT_D32:            return 32;

-	//	case sw::FORMAT_D15S1:          return 15;

-		case sw::FORMAT_D24S8:          return 24;

-		case sw::FORMAT_D24X8:          return 24;

-	//	case sw::FORMAT_D24X4S4:        return 24;

-		case sw::FORMAT_DF16S8:

-		case sw::FORMAT_D16:            return 16;

-		case sw::FORMAT_D32F:

-		case sw::FORMAT_D32F_COMPLEMENTARY:

-		case sw::FORMAT_D32F_LOCKABLE:  return 32;

-		case sw::FORMAT_DF24S8:

-		case sw::FORMAT_D24FS8:         return 24;

-	//	case sw::FORMAT_D32_LOCKABLE:   return 32;

-	//	case sw::FORMAT_S8_LOCKABLE:    return 0;

-		case sw::FORMAT_D32FS8_SHADOW:

-		case sw::FORMAT_D32FS8_TEXTURE: return 32;

-		default:                        return 0;

-		}

-	}

-

-	GLenum GetComponentType(sw::Format format, GLenum attachment)

-	{

-		// Can be one of GL_FLOAT, GL_INT, GL_UNSIGNED_INT, GL_SIGNED_NORMALIZED, or GL_UNSIGNED_NORMALIZED

-		switch(attachment)

-		{

-		case GL_COLOR_ATTACHMENT0:

-		case GL_COLOR_ATTACHMENT1:

-		case GL_COLOR_ATTACHMENT2:

-		case GL_COLOR_ATTACHMENT3:

-		case GL_COLOR_ATTACHMENT4:

-		case GL_COLOR_ATTACHMENT5:

-		case GL_COLOR_ATTACHMENT6:

-		case GL_COLOR_ATTACHMENT7:

-		case GL_COLOR_ATTACHMENT8:

-		case GL_COLOR_ATTACHMENT9:

-		case GL_COLOR_ATTACHMENT10:

-		case GL_COLOR_ATTACHMENT11:

-		case GL_COLOR_ATTACHMENT12:

-		case GL_COLOR_ATTACHMENT13:

-		case GL_COLOR_ATTACHMENT14:

-		case GL_COLOR_ATTACHMENT15:

-		case GL_COLOR_ATTACHMENT16:

-		case GL_COLOR_ATTACHMENT17:

-		case GL_COLOR_ATTACHMENT18:

-		case GL_COLOR_ATTACHMENT19:

-		case GL_COLOR_ATTACHMENT20:

-		case GL_COLOR_ATTACHMENT21:

-		case GL_COLOR_ATTACHMENT22:

-		case GL_COLOR_ATTACHMENT23:

-		case GL_COLOR_ATTACHMENT24:

-		case GL_COLOR_ATTACHMENT25:

-		case GL_COLOR_ATTACHMENT26:

-		case GL_COLOR_ATTACHMENT27:

-		case GL_COLOR_ATTACHMENT28:

-		case GL_COLOR_ATTACHMENT29:

-		case GL_COLOR_ATTACHMENT30:

-		case GL_COLOR_ATTACHMENT31:

-			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_X32B32G32R32F:

-			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:

-			case sw::FORMAT_X8R8G8B8:

-			case sw::FORMAT_X8B8G8R8:

-			case sw::FORMAT_SRGB8_A8:

-			case sw::FORMAT_SRGB8_X8:

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

-			}

-		case GL_DEPTH_ATTACHMENT:

-		case GL_STENCIL_ATTACHMENT:

-			// Only color buffers may have integer components.

-			return GL_FLOAT;

-		default:

-			UNREACHABLE(attachment);

-			return 0;

-		}

-	}

-

-	GLenum ConvertBackBufferFormat(sw::Format format)

-	{

-		switch(format)

-		{

-		case sw::FORMAT_A4R4G4B4: return GL_RGBA4;

-		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;

-		case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES;

-		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;

-		case sw::FORMAT_R5G6B5:   return GL_RGB565;

-		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;

-		case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES;

-		case sw::FORMAT_SRGB8_A8: return GL_RGBA8_OES;

-		case sw::FORMAT_SRGB8_X8: return GL_RGB8_OES;

-		default:

-			UNREACHABLE(format);

-		}

-

-		return GL_RGBA4;

-	}

-

-	GLenum ConvertDepthStencilFormat(sw::Format format)

-	{

-		switch(format)

-		{

-		case sw::FORMAT_D16:

-		case sw::FORMAT_D24X8:

-		case sw::FORMAT_D32:

-			return GL_DEPTH_COMPONENT16;

-		case sw::FORMAT_D24S8:

-			return GL_DEPTH24_STENCIL8_OES;

-		case sw::FORMAT_D32F:

-		case sw::FORMAT_D32F_COMPLEMENTARY:

-		case sw::FORMAT_D32F_LOCKABLE:

-			return GL_DEPTH_COMPONENT32F;

-		case sw::FORMAT_D32FS8_TEXTURE:

-		case sw::FORMAT_D32FS8_SHADOW:

-			return GL_DEPTH32F_STENCIL8;

-		case sw::FORMAT_S8:

-			return GL_STENCIL_INDEX8;

-		default:

-			UNREACHABLE(format);

-		}

-

-		return GL_DEPTH24_STENCIL8_OES;

-	}

-}

+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "utilities.h"
+
+#include "main.h"
+#include "mathutil.h"
+#include "Context.h"
+#include "common/debug.h"
+
+#include <limits>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace es2
+{
+	// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation
+	// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
+	// format and type combinations.
+
+	typedef std::pair<GLenum, GLenum> FormatTypePair;
+	typedef std::pair<FormatTypePair, GLenum> FormatPair;
+	typedef std::map<FormatTypePair, GLenum> FormatMap;
+
+	// A helper function to insert data into the format map with fewer characters.
+	static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat)
+	{
+		map->insert(FormatPair(FormatTypePair(format, type), internalFormat));
+	}
+
+	FormatMap BuildFormatMap()
+	{
+		static const GLenum GL_BGRA4_ANGLEX = 0x6ABC;
+		static const GLenum GL_BGR5_A1_ANGLEX = 0x6ABD;
+
+		FormatMap map;
+
+		//                       | Format | Type | Internal format |
+		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8);
+		InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM);
+		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4);
+		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1);
+		InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2);
+		InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F);
+		InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F);
+		InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F);
+
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I);
+		InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI);
+
+		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8);
+		InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM);
+		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565);
+		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F);
+		InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5);
+		InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F);
+		InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F);
+		InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F);
+
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI);
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I);
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI);
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I);
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI);
+		InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I);
+
+		InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8);
+		InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM);
+		InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F);
+		InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F);
+		InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F);
+
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI);
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I);
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI);
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I);
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI);
+		InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I);
+
+		InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8);
+		InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM);
+		InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F);
+		InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F);
+		InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F);
+
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI);
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I);
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI);
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I);
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI);
+		InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I);
+
+		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT);
+		InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT);
+		InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT);
+		InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT);
+		InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT);
+		InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT);
+
+		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT);
+		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX);
+		InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX);
+
+		InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8);
+		InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8);
+
+		InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+		InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+
+		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16);
+		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES);
+		InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F);
+
+		InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8);
+
+		InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8);
+		InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8);
+
+		return map;
+	}
+
+	GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
+	{
+		switch(internalFormat)
+		{
+		case GL_ALPHA:
+		case GL_LUMINANCE:
+		case GL_LUMINANCE_ALPHA:
+		case GL_RED:
+		case GL_RG:
+		case GL_RGB:
+		case GL_RGBA:
+		case GL_RED_INTEGER:
+		case GL_RG_INTEGER:
+		case GL_RGB_INTEGER:
+		case GL_RGBA_INTEGER:
+		case GL_BGRA_EXT:
+		case GL_DEPTH_COMPONENT:
+		case GL_DEPTH_STENCIL:
+		case GL_SRGB_EXT:
+		case GL_SRGB_ALPHA_EXT:
+			{
+				static const FormatMap formatMap = BuildFormatMap();
+				FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));
+				return (iter != formatMap.end()) ? iter->second : GL_NONE;
+			}
+		default:
+			return internalFormat;
+		}
+	}
+
+	unsigned int UniformComponentCount(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_BOOL:
+		case GL_FLOAT:
+		case GL_INT:
+		case GL_UNSIGNED_INT:
+		case GL_SAMPLER_2D:
+		case GL_SAMPLER_CUBE:
+		case GL_SAMPLER_EXTERNAL_OES:
+		case GL_SAMPLER_3D_OES:
+		case GL_SAMPLER_2D_ARRAY:
+		case GL_SAMPLER_2D_SHADOW:
+		case GL_SAMPLER_CUBE_SHADOW:
+		case GL_SAMPLER_2D_ARRAY_SHADOW:
+		case GL_INT_SAMPLER_2D:
+		case GL_UNSIGNED_INT_SAMPLER_2D:
+		case GL_INT_SAMPLER_CUBE:
+		case GL_UNSIGNED_INT_SAMPLER_CUBE:
+		case GL_INT_SAMPLER_3D:
+		case GL_UNSIGNED_INT_SAMPLER_3D:
+		case GL_INT_SAMPLER_2D_ARRAY:
+		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+			return 1;
+		case GL_BOOL_VEC2:
+		case GL_FLOAT_VEC2:
+		case GL_INT_VEC2:
+		case GL_UNSIGNED_INT_VEC2:
+			return 2;
+		case GL_INT_VEC3:
+		case GL_UNSIGNED_INT_VEC3:
+		case GL_FLOAT_VEC3:
+		case GL_BOOL_VEC3:
+			return 3;
+		case GL_BOOL_VEC4:
+		case GL_FLOAT_VEC4:
+		case GL_INT_VEC4:
+		case GL_UNSIGNED_INT_VEC4:
+		case GL_FLOAT_MAT2:
+			return 4;
+		case GL_FLOAT_MAT2x3:
+		case GL_FLOAT_MAT3x2:
+			return 6;
+		case GL_FLOAT_MAT2x4:
+		case GL_FLOAT_MAT4x2:
+			return 8;
+		case GL_FLOAT_MAT3:
+			return 9;
+		case GL_FLOAT_MAT3x4:
+		case GL_FLOAT_MAT4x3:
+			return 12;
+		case GL_FLOAT_MAT4:
+			return 16;
+		default:
+			UNREACHABLE(type);
+		}
+
+		return 0;
+	}
+
+	GLenum UniformComponentType(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_BOOL:
+		case GL_BOOL_VEC2:
+		case GL_BOOL_VEC3:
+		case GL_BOOL_VEC4:
+			return GL_BOOL;
+		case GL_FLOAT:
+		case GL_FLOAT_VEC2:
+		case GL_FLOAT_VEC3:
+		case GL_FLOAT_VEC4:
+		case GL_FLOAT_MAT2:
+		case GL_FLOAT_MAT2x3:
+		case GL_FLOAT_MAT2x4:
+		case GL_FLOAT_MAT3:
+		case GL_FLOAT_MAT3x2:
+		case GL_FLOAT_MAT3x4:
+		case GL_FLOAT_MAT4:
+		case GL_FLOAT_MAT4x2:
+		case GL_FLOAT_MAT4x3:
+			return GL_FLOAT;
+		case GL_INT:
+		case GL_SAMPLER_2D:
+		case GL_SAMPLER_CUBE:
+		case GL_SAMPLER_EXTERNAL_OES:
+		case GL_SAMPLER_3D_OES:
+		case GL_SAMPLER_2D_ARRAY:
+		case GL_SAMPLER_2D_SHADOW:
+		case GL_SAMPLER_CUBE_SHADOW:
+		case GL_SAMPLER_2D_ARRAY_SHADOW:
+		case GL_INT_SAMPLER_2D:
+		case GL_UNSIGNED_INT_SAMPLER_2D:
+		case GL_INT_SAMPLER_CUBE:
+		case GL_UNSIGNED_INT_SAMPLER_CUBE:
+		case GL_INT_SAMPLER_3D:
+		case GL_UNSIGNED_INT_SAMPLER_3D:
+		case GL_INT_SAMPLER_2D_ARRAY:
+		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+		case GL_INT_VEC2:
+		case GL_INT_VEC3:
+		case GL_INT_VEC4:
+			return GL_INT;
+		case GL_UNSIGNED_INT:
+		case GL_UNSIGNED_INT_VEC2:
+		case GL_UNSIGNED_INT_VEC3:
+		case GL_UNSIGNED_INT_VEC4:
+			return GL_UNSIGNED_INT;
+		default:
+			UNREACHABLE(type);
+		}
+
+		return GL_NONE;
+	}
+
+	size_t UniformTypeSize(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_BOOL:  return sizeof(GLboolean);
+		case GL_FLOAT: return sizeof(GLfloat);
+		case GL_INT:   return sizeof(GLint);
+		case GL_UNSIGNED_INT: return sizeof(GLuint);
+		}
+
+		return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
+	}
+
+	bool IsSamplerUniform(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_SAMPLER_2D:
+		case GL_SAMPLER_CUBE:
+		case GL_SAMPLER_EXTERNAL_OES:
+		case GL_SAMPLER_3D_OES:
+		case GL_SAMPLER_2D_ARRAY:
+		case GL_SAMPLER_2D_SHADOW:
+		case GL_SAMPLER_CUBE_SHADOW:
+		case GL_SAMPLER_2D_ARRAY_SHADOW:
+		case GL_INT_SAMPLER_2D:
+		case GL_UNSIGNED_INT_SAMPLER_2D:
+		case GL_INT_SAMPLER_CUBE:
+		case GL_UNSIGNED_INT_SAMPLER_CUBE:
+		case GL_INT_SAMPLER_3D:
+		case GL_UNSIGNED_INT_SAMPLER_3D:
+		case GL_INT_SAMPLER_2D_ARRAY:
+		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+			return true;
+		default:
+			return false;
+		}
+	}
+
+	int VariableRowCount(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_NONE:
+			return 0;
+		case GL_BOOL:
+		case GL_FLOAT:
+		case GL_INT:
+		case GL_UNSIGNED_INT:
+		case GL_BOOL_VEC2:
+		case GL_FLOAT_VEC2:
+		case GL_INT_VEC2:
+		case GL_UNSIGNED_INT_VEC2:
+		case GL_INT_VEC3:
+		case GL_UNSIGNED_INT_VEC3:
+		case GL_FLOAT_VEC3:
+		case GL_BOOL_VEC3:
+		case GL_BOOL_VEC4:
+		case GL_FLOAT_VEC4:
+		case GL_INT_VEC4:
+		case GL_UNSIGNED_INT_VEC4:
+		case GL_SAMPLER_2D:
+		case GL_SAMPLER_CUBE:
+		case GL_SAMPLER_EXTERNAL_OES:
+		case GL_SAMPLER_3D_OES:
+		case GL_SAMPLER_2D_ARRAY:
+		case GL_SAMPLER_2D_SHADOW:
+		case GL_SAMPLER_CUBE_SHADOW:
+		case GL_SAMPLER_2D_ARRAY_SHADOW:
+		case GL_INT_SAMPLER_2D:
+		case GL_UNSIGNED_INT_SAMPLER_2D:
+		case GL_INT_SAMPLER_CUBE:
+		case GL_UNSIGNED_INT_SAMPLER_CUBE:
+		case GL_INT_SAMPLER_3D:
+		case GL_UNSIGNED_INT_SAMPLER_3D:
+		case GL_INT_SAMPLER_2D_ARRAY:
+		case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+			return 1;
+		case GL_FLOAT_MAT2:
+		case GL_FLOAT_MAT3x2:
+		case GL_FLOAT_MAT4x2:
+			return 2;
+		case GL_FLOAT_MAT3:
+		case GL_FLOAT_MAT2x3:
+		case GL_FLOAT_MAT4x3:
+			return 3;
+		case GL_FLOAT_MAT4:
+		case GL_FLOAT_MAT2x4:
+		case GL_FLOAT_MAT3x4:
+			return 4;
+		default:
+			UNREACHABLE(type);
+		}
+
+		return 0;
+	}
+
+	int VariableColumnCount(GLenum type)
+	{
+		switch(type)
+		{
+		case GL_NONE:
+			return 0;
+		case GL_BOOL:
+		case GL_FLOAT:
+		case GL_INT:
+		case GL_UNSIGNED_INT:
+			return 1;
+		case GL_BOOL_VEC2:
+		case GL_FLOAT_VEC2:
+		case GL_INT_VEC2:
+		case GL_UNSIGNED_INT_VEC2:
+		case GL_FLOAT_MAT2:
+		case GL_FLOAT_MAT2x3:
+		case GL_FLOAT_MAT2x4:
+			return 2;
+		case GL_INT_VEC3:
+		case GL_UNSIGNED_INT_VEC3:
+		case GL_FLOAT_VEC3:
+		case GL_BOOL_VEC3:
+		case GL_FLOAT_MAT3:
+		case GL_FLOAT_MAT3x2:
+		case GL_FLOAT_MAT3x4:
+			return 3;
+		case GL_BOOL_VEC4:
+		case GL_FLOAT_VEC4:
+		case GL_INT_VEC4:
+		case GL_UNSIGNED_INT_VEC4:
+		case GL_FLOAT_MAT4:
+		case GL_FLOAT_MAT4x2:
+		case GL_FLOAT_MAT4x3:
+			return 4;
+		default:
+			UNREACHABLE(type);
+		}
+
+		return 0;
+	}
+
+	int VariableRegisterCount(GLenum type)
+	{
+		// Number of registers used is the number of columns for matrices or 1 for scalars and vectors
+		return (VariableRowCount(type) > 1) ? VariableColumnCount(type) : 1;
+	}
+
+	int VariableRegisterSize(GLenum type)
+	{
+		// Number of components per register is the number of rows for matrices or columns for scalars and vectors
+		int nbRows = VariableRowCount(type);
+		return (nbRows > 1) ? nbRows : VariableColumnCount(type);
+	}
+
+	int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+	{
+		ASSERT(allocationSize <= bitsSize);
+
+		unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+		for(unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+		{
+			if((*bits & mask) == 0)
+			{
+				*bits |= mask;
+				return i;
+			}
+
+			mask <<= 1;
+		}
+
+		return -1;
+	}
+
+	GLint floatToInt(GLfloat value)
+	{
+		return static_cast<GLint>((static_cast<GLfloat>(0xFFFFFFFF) * value - 1.0f) * 0.5f);
+	}
+
+	bool IsCompressed(GLenum format, GLint clientVersion)
+	{
+		return ValidateCompressedFormat(format, clientVersion, true) == GL_NONE;
+	}
+
+	GLenum ValidateCompressedFormat(GLenum format, GLint clientVersion, bool expectCompressedFormats)
+	{
+		switch(format)
+		{
+		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+		case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+		case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+			return S3TC_SUPPORT ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;
+		case GL_ETC1_RGB8_OES:
+			return expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION;
+		case GL_COMPRESSED_R11_EAC:
+		case GL_COMPRESSED_SIGNED_R11_EAC:
+		case GL_COMPRESSED_RG11_EAC:
+		case GL_COMPRESSED_SIGNED_RG11_EAC:
+		case GL_COMPRESSED_RGB8_ETC2:
+		case GL_COMPRESSED_SRGB8_ETC2:
+		case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+		case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+		case GL_COMPRESSED_RGBA8_ETC2_EAC:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+		case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+		case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+		case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+			return (clientVersion >= 3) ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;
+		default:
+			return expectCompressedFormats ? GL_INVALID_ENUM : GL_NONE; // Not compressed format
+		}
+	}
+
+	GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)
+	{
+		if(!texture)
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(compressed != texture->isCompressed(target, level))
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(sizedInternalFormat != GL_NONE && sizedInternalFormat != texture->getFormat(target, level))
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(compressed)
+		{
+			if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
+			   (height % 4 != 0 && height != texture->getHeight(target, 0)))
+			{
+				return GL_INVALID_OPERATION;
+			}
+		}
+
+		if(xoffset + width > texture->getWidth(target, level) ||
+		   yoffset + height > texture->getHeight(target, level))
+		{
+			return GL_INVALID_VALUE;
+		}
+
+		return GL_NONE;
+	}
+
+	GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)
+	{
+		if(!texture)
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(compressed != texture->isCompressed(target, level))
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(sizedInternalFormat != GL_NONE && sizedInternalFormat != GetSizedInternalFormat(texture->getFormat(target, level), texture->getType(target, level)))
+		{
+			return GL_INVALID_OPERATION;
+		}
+
+		if(compressed)
+		{
+			if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
+			   (height % 4 != 0 && height != texture->getHeight(target, 0)) ||
+			   (depth % 4 != 0 && depth != texture->getDepth(target, 0)))
+			{
+				return GL_INVALID_OPERATION;
+			}
+		}
+
+		if(xoffset + width > texture->getWidth(target, level) ||
+		   yoffset + height > texture->getHeight(target, level) ||
+		   zoffset + depth > texture->getDepth(target, level))
+		{
+			return GL_INVALID_VALUE;
+		}
+
+		return GL_NONE;
+	}
+
+	bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, 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);
+		case GL_DEPTH_COMPONENT:
+			if(internalFormat != format)
+			{
+				return false;
+			}
+			switch(type)
+			{
+			case GL_UNSIGNED_SHORT:
+			case GL_FLOAT:
+				if(internalType != type)
+				{
+					return false;
+				}
+				break;
+			default:
+				return false;
+			}
+			break;
+		default:
+			return false;
+		}
+		return true;
+	}
+
+	bool IsDepthTexture(GLenum format)
+	{
+		return format == GL_DEPTH_COMPONENT ||
+		       format == GL_DEPTH_STENCIL_OES ||
+		       format == GL_DEPTH_COMPONENT16 ||
+		       format == GL_DEPTH_COMPONENT24 ||
+		       format == GL_DEPTH_COMPONENT32_OES ||
+		       format == GL_DEPTH_COMPONENT32F ||
+		       format == GL_DEPTH24_STENCIL8 ||
+		       format == GL_DEPTH32F_STENCIL8;
+	}
+
+	bool IsStencilTexture(GLenum format)
+	{
+		return format == GL_STENCIL_INDEX_OES ||
+		       format == GL_DEPTH_STENCIL_OES ||
+		       format == GL_DEPTH24_STENCIL8 ||
+		       format == GL_DEPTH32F_STENCIL8;
+	}
+
+	bool IsCubemapTextureTarget(GLenum target)
+	{
+		return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+	}
+
+	int CubeFaceIndex(GLenum cubeFace)
+	{
+		switch(cubeFace)
+		{
+		case GL_TEXTURE_CUBE_MAP:
+		case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0;
+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: return 1;
+		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: return 2;
+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: return 3;
+		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: return 4;
+		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return 5;
+		default: UNREACHABLE(cubeFace); return 0;
+		}
+	}
+
+	bool IsTextureTarget(GLenum target)
+	{
+		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) || target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
+	}
+
+	bool ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion)
+	{
+		switch(type)
+		{
+		case GL_UNSIGNED_BYTE:
+		case GL_UNSIGNED_SHORT_4_4_4_4:
+		case GL_UNSIGNED_SHORT_5_5_5_1:
+		case GL_UNSIGNED_SHORT_5_6_5:
+		case GL_FLOAT:               // GL_OES_texture_float
+		case GL_HALF_FLOAT_OES:      // GL_OES_texture_half_float
+		case GL_UNSIGNED_INT_24_8:   // GL_OES_packed_depth_stencil (GL_UNSIGNED_INT_24_8_EXT)
+		case GL_UNSIGNED_SHORT:      // GL_OES_depth_texture
+		case GL_UNSIGNED_INT:        // GL_OES_depth_texture
+			break;
+		case GL_BYTE:
+		case GL_SHORT:
+		case GL_INT:
+		case GL_HALF_FLOAT:
+		case GL_UNSIGNED_INT_2_10_10_10_REV:
+		case GL_UNSIGNED_INT_10F_11F_11F_REV:
+		case GL_UNSIGNED_INT_5_9_9_9_REV:
+		case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+			if(clientVersion < 3)
+			{
+				return error(GL_INVALID_ENUM, false);
+			}
+			break;
+		default:
+			return error(GL_INVALID_ENUM, false);
+		}
+
+		switch(format)
+		{
+		case GL_ALPHA:
+		case GL_RGB:
+		case GL_RGBA:
+		case GL_LUMINANCE:
+		case GL_LUMINANCE_ALPHA:
+		case GL_BGRA_EXT:          // GL_EXT_texture_format_BGRA8888
+		case GL_DEPTH_STENCIL:     // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES)
+		case GL_DEPTH_COMPONENT:   // GL_OES_depth_texture
+			break;
+		case GL_RED:
+		case GL_RED_INTEGER:
+		case GL_RG:
+		case GL_RG_INTEGER:
+		case GL_RGB_INTEGER:
+		case GL_RGBA_INTEGER:
+			if(clientVersion < 3)
+			{
+				return error(GL_INVALID_ENUM, false);
+			}
+			break;
+		default:
+			return error(GL_INVALID_ENUM, false);
+		}
+
+		if(internalformat != format)
+		{
+			if(clientVersion < 3)
+			{
+				return error(GL_INVALID_OPERATION, false);
+			}
+
+			switch(internalformat)
+			{
+			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_RGB8UI:
+			case GL_RGB8I:
+			case GL_RGB16UI:
+			case GL_RGB16I:
+			case GL_RGB32UI:
+			case GL_RGB32I:
+			case GL_RG8_SNORM:
+			case GL_R8_SNORM:
+			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_RGBA4:
+			case GL_RGB5_A1:
+			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_COMPONENT24:
+			case GL_DEPTH_COMPONENT32_OES:
+			case GL_DEPTH_COMPONENT32F:
+			case GL_DEPTH32F_STENCIL8:
+			case GL_DEPTH_COMPONENT16:
+			case GL_STENCIL_INDEX8:
+			case GL_DEPTH24_STENCIL8_OES:
+			case GL_RGBA8_SNORM:
+			case GL_SRGB8:
+			case GL_RGB8_SNORM:
+			case GL_RGB9_E5:
+				break;
+			default:
+				return error(GL_INVALID_ENUM, false);
+			}
+		}
+
+		// Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2]
+		bool validSizedInternalformat = false;
+		#define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break;
+
+		switch(format)
+		{
+		case GL_RGBA:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8, GL_RGB5_A1, GL_RGBA4, GL_SRGB8_ALPHA8)
+			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGBA8_SNORM)
+			case GL_HALF_FLOAT_OES:              break;
+			case GL_UNSIGNED_SHORT_4_4_4_4:      VALIDATE_INTERNALFORMAT(GL_RGBA4)
+			case GL_UNSIGNED_SHORT_5_5_5_1:      VALIDATE_INTERNALFORMAT(GL_RGB5_A1)
+			case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2, GL_RGB5_A1)
+			case GL_HALF_FLOAT:                  VALIDATE_INTERNALFORMAT(GL_RGBA16F)
+			case GL_FLOAT:                       VALIDATE_INTERNALFORMAT(GL_RGBA32F, GL_RGBA16F)
+			default:                             return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RGBA_INTEGER:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGBA8UI)
+			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGBA8I)
+			case GL_UNSIGNED_SHORT:              VALIDATE_INTERNALFORMAT(GL_RGBA16UI)
+			case GL_SHORT:                       VALIDATE_INTERNALFORMAT(GL_RGBA16I)
+			case GL_UNSIGNED_INT:                VALIDATE_INTERNALFORMAT(GL_RGBA32UI)
+			case GL_INT:                         VALIDATE_INTERNALFORMAT(GL_RGBA32I)
+			case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2UI)
+			default:                             return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RGB:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:                VALIDATE_INTERNALFORMAT(GL_RGB8, GL_RGB565, GL_SRGB8)
+			case GL_BYTE:                         VALIDATE_INTERNALFORMAT(GL_RGB8_SNORM)
+			case GL_HALF_FLOAT_OES:               break;
+			case GL_UNSIGNED_SHORT_5_6_5:         VALIDATE_INTERNALFORMAT(GL_RGB565)
+			case GL_UNSIGNED_INT_10F_11F_11F_REV: VALIDATE_INTERNALFORMAT(GL_R11F_G11F_B10F)
+			case GL_UNSIGNED_INT_5_9_9_9_REV:     VALIDATE_INTERNALFORMAT(GL_RGB9_E5)
+			case GL_HALF_FLOAT:                   VALIDATE_INTERNALFORMAT(GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)
+			case GL_FLOAT:                        VALIDATE_INTERNALFORMAT(GL_RGB32F, GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)
+			default:                              return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RGB_INTEGER:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:               VALIDATE_INTERNALFORMAT(GL_RGB8UI)
+			case GL_BYTE:                        VALIDATE_INTERNALFORMAT(GL_RGB8I)
+			case GL_UNSIGNED_SHORT:              VALIDATE_INTERNALFORMAT(GL_RGB16UI)
+			case GL_SHORT:                       VALIDATE_INTERNALFORMAT(GL_RGB16I)
+			case GL_UNSIGNED_INT:                VALIDATE_INTERNALFORMAT(GL_RGB32UI)
+			case GL_INT:                         VALIDATE_INTERNALFORMAT(GL_RGB32I)
+			default:                             return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RG:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RG8)
+			case GL_BYTE:          VALIDATE_INTERNALFORMAT(GL_RG8_SNORM)
+			case GL_HALF_FLOAT:    VALIDATE_INTERNALFORMAT(GL_RG16F)
+			case GL_FLOAT:         VALIDATE_INTERNALFORMAT(GL_RG32F, GL_RG16F)
+			default:               return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RG_INTEGER:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_RG8UI)
+			case GL_BYTE:           VALIDATE_INTERNALFORMAT(GL_RG8I)
+			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_RG16UI)
+			case GL_SHORT:          VALIDATE_INTERNALFORMAT(GL_RG16I)
+			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_RG32UI)
+			case GL_INT:            VALIDATE_INTERNALFORMAT(GL_RG32I)
+			default:                return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RED:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_R8)
+			case GL_BYTE:          VALIDATE_INTERNALFORMAT(GL_R8_SNORM)
+			case GL_HALF_FLOAT:    VALIDATE_INTERNALFORMAT(GL_R16F)
+			case GL_FLOAT:         VALIDATE_INTERNALFORMAT(GL_R32F, GL_R16F)
+			default:               return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_RED_INTEGER:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:  VALIDATE_INTERNALFORMAT(GL_R8UI)
+			case GL_BYTE:           VALIDATE_INTERNALFORMAT(GL_R8I)
+			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_R16UI)
+			case GL_SHORT:          VALIDATE_INTERNALFORMAT(GL_R16I)
+			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_R32UI)
+			case GL_INT:            VALIDATE_INTERNALFORMAT(GL_R32I)
+			default:                return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_DEPTH_COMPONENT:
+			switch(type)
+			{
+			case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT16)
+			case GL_UNSIGNED_INT:   VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16)
+			case GL_FLOAT:          VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT32F)
+			default:                return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_DEPTH_STENCIL:
+			switch(type)
+			{
+			case GL_UNSIGNED_INT_24_8:              VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8)
+			case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: VALIDATE_INTERNALFORMAT(GL_DEPTH32F_STENCIL8)
+			default:                                return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_LUMINANCE_ALPHA:
+		case GL_LUMINANCE:
+		case GL_ALPHA:
+			switch(type)
+			{
+			case GL_UNSIGNED_BYTE:
+			case GL_HALF_FLOAT_OES:
+			case GL_FLOAT:
+				break;
+			default:
+				return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		case GL_BGRA_EXT:
+			if(type != GL_UNSIGNED_BYTE)
+			{
+				return error(GL_INVALID_OPERATION, false);
+			}
+			break;
+		default:
+			UNREACHABLE(format);
+			return error(GL_INVALID_ENUM, false);
+		}
+
+		#undef VALIDATE_INTERNALFORMAT
+
+		if(internalformat != format && !validSizedInternalformat)
+		{
+			return error(GL_INVALID_OPERATION, false);
+		}
+
+		return true;
+	}
+
+	bool IsColorRenderable(GLenum internalformat, GLint clientVersion)
+	{
+		switch(internalformat)
+		{
+		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:
+		case GL_BGRA8_EXT:
+			return true;
+		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:
+			return clientVersion >= 3;
+		case GL_DEPTH_COMPONENT24:
+		case GL_DEPTH_COMPONENT32_OES:
+		case GL_DEPTH_COMPONENT32F:
+		case GL_DEPTH32F_STENCIL8:
+		case GL_DEPTH_COMPONENT16:
+		case GL_STENCIL_INDEX8:
+		case GL_DEPTH24_STENCIL8_OES:
+			return false;
+		default:
+			UNIMPLEMENTED();
+		}
+
+		return false;
+	}
+
+	bool IsDepthRenderable(GLenum internalformat)
+	{
+		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:
+			return true;
+		case GL_STENCIL_INDEX8:
+		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_RGBA4:
+		case GL_RGB5_A1:
+		case GL_RGB565:
+		case GL_RGB8_OES:
+		case GL_RGBA8_OES:
+		case GL_RGB:
+		case GL_RGBA:
+		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();
+		}
+
+		return false;
+	}
+
+	bool IsStencilRenderable(GLenum internalformat)
+	{
+		switch(internalformat)
+		{
+		case GL_DEPTH32F_STENCIL8:
+		case GL_STENCIL_INDEX8:
+		case GL_DEPTH24_STENCIL8_OES:
+			return true;
+		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_RGBA4:
+		case GL_RGB5_A1:
+		case GL_RGB565:
+		case GL_RGB8_OES:
+		case GL_RGBA8_OES:
+		case GL_RGB:
+		case GL_RGBA:
+		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:
+			UNIMPLEMENTED();
+		}
+
+		return false;
+	}
+
+	std::string ParseUniformName(const std::string &name, size_t *outSubscript)
+	{
+		// Strip any trailing array operator and retrieve the subscript
+		size_t open = name.find_last_of('[');
+		size_t close = name.find_last_of(']');
+		bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
+		if(!hasIndex)
+		{
+			if(outSubscript)
+			{
+				*outSubscript = GL_INVALID_INDEX;
+			}
+			return name;
+		}
+
+		if(outSubscript)
+		{
+			int index = atoi(name.substr(open + 1).c_str());
+			if(index >= 0)
+			{
+				*outSubscript = index;
+			}
+			else
+			{
+				*outSubscript = GL_INVALID_INDEX;
+			}
+		}
+
+		return name.substr(0, open);
+	}
+}
+
+namespace es2sw
+{
+	sw::DepthCompareMode ConvertDepthComparison(GLenum comparison)
+	{
+		switch(comparison)
+		{
+		case GL_NEVER:    return sw::DEPTH_NEVER;
+		case GL_ALWAYS:   return sw::DEPTH_ALWAYS;
+		case GL_LESS:     return sw::DEPTH_LESS;
+		case GL_LEQUAL:   return sw::DEPTH_LESSEQUAL;
+		case GL_EQUAL:    return sw::DEPTH_EQUAL;
+		case GL_GREATER:  return sw::DEPTH_GREATER;
+		case GL_GEQUAL:   return sw::DEPTH_GREATEREQUAL;
+		case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL;
+		default: UNREACHABLE(comparison);
+		}
+
+		return sw::DEPTH_ALWAYS;
+	}
+
+	sw::StencilCompareMode ConvertStencilComparison(GLenum comparison)
+	{
+		switch(comparison)
+		{
+		case GL_NEVER:    return sw::STENCIL_NEVER;
+		case GL_ALWAYS:   return sw::STENCIL_ALWAYS;
+		case GL_LESS:     return sw::STENCIL_LESS;
+		case GL_LEQUAL:   return sw::STENCIL_LESSEQUAL;
+		case GL_EQUAL:    return sw::STENCIL_EQUAL;
+		case GL_GREATER:  return sw::STENCIL_GREATER;
+		case GL_GEQUAL:   return sw::STENCIL_GREATEREQUAL;
+		case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL;
+		default: UNREACHABLE(comparison);
+		}
+
+		return sw::STENCIL_ALWAYS;
+	}
+
+	sw::Color<float> ConvertColor(es2::Color color)
+	{
+		return sw::Color<float>(color.red, color.green, color.blue, color.alpha);
+	}
+
+	sw::BlendFactor ConvertBlendFunc(GLenum blend)
+	{
+		switch(blend)
+		{
+		case GL_ZERO:                     return sw::BLEND_ZERO;
+		case GL_ONE:                      return sw::BLEND_ONE;
+		case GL_SRC_COLOR:                return sw::BLEND_SOURCE;
+		case GL_ONE_MINUS_SRC_COLOR:      return sw::BLEND_INVSOURCE;
+		case GL_DST_COLOR:                return sw::BLEND_DEST;
+		case GL_ONE_MINUS_DST_COLOR:      return sw::BLEND_INVDEST;
+		case GL_SRC_ALPHA:                return sw::BLEND_SOURCEALPHA;
+		case GL_ONE_MINUS_SRC_ALPHA:      return sw::BLEND_INVSOURCEALPHA;
+		case GL_DST_ALPHA:                return sw::BLEND_DESTALPHA;
+		case GL_ONE_MINUS_DST_ALPHA:      return sw::BLEND_INVDESTALPHA;
+		case GL_CONSTANT_COLOR:           return sw::BLEND_CONSTANT;
+		case GL_ONE_MINUS_CONSTANT_COLOR: return sw::BLEND_INVCONSTANT;
+		case GL_CONSTANT_ALPHA:           return sw::BLEND_CONSTANTALPHA;
+		case GL_ONE_MINUS_CONSTANT_ALPHA: return sw::BLEND_INVCONSTANTALPHA;
+		case GL_SRC_ALPHA_SATURATE:       return sw::BLEND_SRCALPHASAT;
+		default: UNREACHABLE(blend);
+		}
+
+		return sw::BLEND_ZERO;
+	}
+
+	sw::BlendOperation ConvertBlendOp(GLenum blendOp)
+	{
+		switch(blendOp)
+		{
+		case GL_FUNC_ADD:              return sw::BLENDOP_ADD;
+		case GL_FUNC_SUBTRACT:         return sw::BLENDOP_SUB;
+		case GL_FUNC_REVERSE_SUBTRACT: return sw::BLENDOP_INVSUB;
+		case GL_MIN_EXT:               return sw::BLENDOP_MIN;
+		case GL_MAX_EXT:               return sw::BLENDOP_MAX;
+		default: UNREACHABLE(blendOp);
+		}
+
+		return sw::BLENDOP_ADD;
+	}
+
+	sw::StencilOperation ConvertStencilOp(GLenum stencilOp)
+	{
+		switch(stencilOp)
+		{
+		case GL_ZERO:      return sw::OPERATION_ZERO;
+		case GL_KEEP:      return sw::OPERATION_KEEP;
+		case GL_REPLACE:   return sw::OPERATION_REPLACE;
+		case GL_INCR:      return sw::OPERATION_INCRSAT;
+		case GL_DECR:      return sw::OPERATION_DECRSAT;
+		case GL_INVERT:    return sw::OPERATION_INVERT;
+		case GL_INCR_WRAP: return sw::OPERATION_INCR;
+		case GL_DECR_WRAP: return sw::OPERATION_DECR;
+		default: UNREACHABLE(stencilOp);
+		}
+
+		return sw::OPERATION_KEEP;
+	}
+
+	sw::AddressingMode ConvertTextureWrap(GLenum wrap)
+	{
+		switch(wrap)
+		{
+		case GL_REPEAT:            return sw::ADDRESSING_WRAP;
+		case GL_CLAMP_TO_EDGE:     return sw::ADDRESSING_CLAMP;
+		case GL_MIRRORED_REPEAT:   return sw::ADDRESSING_MIRROR;
+		default: UNREACHABLE(wrap);
+		}
+
+		return sw::ADDRESSING_WRAP;
+	}
+
+	sw::SwizzleType ConvertSwizzleType(GLenum swizzleType)
+	{
+		switch(swizzleType)
+		{
+		case GL_RED:   return sw::SWIZZLE_RED;
+		case GL_GREEN: return sw::SWIZZLE_GREEN;
+		case GL_BLUE:  return sw::SWIZZLE_BLUE;
+		case GL_ALPHA: return sw::SWIZZLE_ALPHA;
+		case GL_ZERO:  return sw::SWIZZLE_ZERO;
+		case GL_ONE:   return sw::SWIZZLE_ONE;
+		default: UNREACHABLE(swizzleType);
+		}
+
+		return sw::SWIZZLE_RED;
+	};
+
+	sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace)
+	{
+		switch(cullFace)
+		{
+		case GL_FRONT:
+			return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE);
+		case GL_BACK:
+			return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE);
+		case GL_FRONT_AND_BACK:
+			return sw::CULL_NONE;   // culling will be handled during draw
+		default: UNREACHABLE(cullFace);
+		}
+
+		return sw::CULL_COUNTERCLOCKWISE;
+	}
+
+	unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+	{
+		return (red   ? 0x00000001 : 0) |
+			   (green ? 0x00000002 : 0) |
+			   (blue  ? 0x00000004 : 0) |
+			   (alpha ? 0x00000008 : 0);
+	}
+
+	sw::MipmapType ConvertMipMapFilter(GLenum minFilter)
+	{
+		switch(minFilter)
+		{
+		case GL_NEAREST:
+		case GL_LINEAR:
+			return sw::MIPMAP_NONE;
+			break;
+		case GL_NEAREST_MIPMAP_NEAREST:
+		case GL_LINEAR_MIPMAP_NEAREST:
+			return sw::MIPMAP_POINT;
+			break;
+		case GL_NEAREST_MIPMAP_LINEAR:
+		case GL_LINEAR_MIPMAP_LINEAR:
+			return sw::MIPMAP_LINEAR;
+			break;
+		default:
+			UNREACHABLE(minFilter);
+			return sw::MIPMAP_NONE;
+		}
+	}
+
+	sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
+	{
+		if(maxAnisotropy > 1.0f)
+		{
+			return sw::FILTER_ANISOTROPIC;
+		}
+
+		sw::FilterType magFilterType = sw::FILTER_POINT;
+		switch(magFilter)
+		{
+		case GL_NEAREST: magFilterType = sw::FILTER_POINT;  break;
+		case GL_LINEAR:  magFilterType = sw::FILTER_LINEAR; break;
+		default: UNREACHABLE(magFilter);
+		}
+
+		switch(minFilter)
+		{
+		case GL_NEAREST:
+		case GL_NEAREST_MIPMAP_NEAREST:
+		case GL_NEAREST_MIPMAP_LINEAR:
+			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
+		case GL_LINEAR:
+		case GL_LINEAR_MIPMAP_NEAREST:
+		case GL_LINEAR_MIPMAP_LINEAR:
+			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR;
+		default:
+			UNREACHABLE(minFilter);
+			return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR;
+		}
+	}
+
+	bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType,  sw::DrawType &drawType, int &primitiveCount)
+	{
+		switch(primitiveType)
+		{
+		case GL_POINTS:
+			drawType = sw::DRAW_POINTLIST;
+			primitiveCount = elementCount;
+			break;
+		case GL_LINES:
+			drawType = sw::DRAW_LINELIST;
+			primitiveCount = elementCount / 2;
+			break;
+		case GL_LINE_LOOP:
+			drawType = sw::DRAW_LINELOOP;
+			primitiveCount = elementCount;
+			break;
+		case GL_LINE_STRIP:
+			drawType = sw::DRAW_LINESTRIP;
+			primitiveCount = elementCount - 1;
+			break;
+		case GL_TRIANGLES:
+			drawType = sw::DRAW_TRIANGLELIST;
+			primitiveCount = elementCount / 3;
+			break;
+		case GL_TRIANGLE_STRIP:
+			drawType = sw::DRAW_TRIANGLESTRIP;
+			primitiveCount = elementCount - 2;
+			break;
+		case GL_TRIANGLE_FAN:
+			drawType = sw::DRAW_TRIANGLEFAN;
+			primitiveCount = elementCount - 2;
+			break;
+		default:
+			return false;
+		}
+
+		sw::DrawType elementSize;
+		switch(elementType)
+		{
+		case GL_NONE:           elementSize = sw::DRAW_NONINDEXED; break;
+		case GL_UNSIGNED_BYTE:  elementSize = sw::DRAW_INDEXED8;   break;
+		case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16;  break;
+		case GL_UNSIGNED_INT:   elementSize = sw::DRAW_INDEXED32;  break;
+		default: return false;
+		}
+
+		drawType = sw::DrawType(drawType | elementSize);
+
+		return true;
+	}
+
+	sw::Format ConvertRenderbufferFormat(GLenum format)
+	{
+		switch(format)
+		{
+		case GL_RGBA4:
+		case GL_RGB5_A1:
+		case GL_RGBA8_OES:            return sw::FORMAT_A8B8G8R8;
+		case GL_RGB565:               return sw::FORMAT_R5G6B5;
+		case GL_RGB8_OES:             return sw::FORMAT_X8B8G8R8;
+		case GL_DEPTH_COMPONENT16:
+		case GL_STENCIL_INDEX8:
+		case GL_DEPTH24_STENCIL8_OES: return sw::FORMAT_D24S8;
+		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:                return sw::FORMAT_SRGB8_X8;
+		case GL_SRGB8_ALPHA8:         return sw::FORMAT_SRGB8_A8;
+		default: UNREACHABLE(format); return sw::FORMAT_NULL;
+		}
+	}
+}
+
+namespace sw2es
+{
+	unsigned int GetStencilSize(sw::Format stencilFormat)
+	{
+		switch(stencilFormat)
+		{
+		case sw::FORMAT_D24FS8:
+		case sw::FORMAT_D24S8:
+		case sw::FORMAT_D32FS8_TEXTURE:
+		case sw::FORMAT_D32FS8_SHADOW:
+		case sw::FORMAT_S8:
+			return 8;
+	//	case sw::FORMAT_D24X4S4:
+	//		return 4;
+	//	case sw::FORMAT_D15S1:
+	//		return 1;
+	//	case sw::FORMAT_D16_LOCKABLE:
+		case sw::FORMAT_D32:
+		case sw::FORMAT_D24X8:
+		case sw::FORMAT_D32F_LOCKABLE:
+		case sw::FORMAT_D16:
+			return 0;
+	//	case sw::FORMAT_D32_LOCKABLE:  return 0;
+	//	case sw::FORMAT_S8_LOCKABLE:   return 8;
+		default:
+			return 0;
+		}
+	}
+
+	unsigned int GetAlphaSize(sw::Format colorFormat)
+	{
+		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_SRGB8_A8:
+		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:
+		case sw::FORMAT_X8B8G8R8:
+		case sw::FORMAT_SRGB8_X8:
+		case sw::FORMAT_R5G6B5:
+			return 0;
+		default:
+			return 0;
+		}
+	}
+
+	unsigned int GetRedSize(sw::Format colorFormat)
+	{
+		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_X32B32G32R32F:
+		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_SRGB8_A8:
+		case sw::FORMAT_SRGB8_X8:
+		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:
+			return 5;
+		default:
+			return 0;
+		}
+	}
+
+	unsigned int GetGreenSize(sw::Format colorFormat)
+	{
+		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_X32B32G32R32F:
+		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_SRGB8_A8:
+		case sw::FORMAT_SRGB8_X8:
+		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;
+		case sw::FORMAT_R5G6B5:
+			return 6;
+		default:
+			return 0;
+		}
+	}
+
+	unsigned int GetBlueSize(sw::Format colorFormat)
+	{
+		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_X32B32G32R32F:
+		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_SRGB8_A8:
+		case sw::FORMAT_SRGB8_X8:
+		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:
+			return 5;
+		default:
+			return 0;
+		}
+	}
+
+	unsigned int GetDepthSize(sw::Format depthFormat)
+	{
+		switch(depthFormat)
+		{
+	//	case sw::FORMAT_D16_LOCKABLE:   return 16;
+		case sw::FORMAT_D32:            return 32;
+	//	case sw::FORMAT_D15S1:          return 15;
+		case sw::FORMAT_D24S8:          return 24;
+		case sw::FORMAT_D24X8:          return 24;
+	//	case sw::FORMAT_D24X4S4:        return 24;
+		case sw::FORMAT_DF16S8:
+		case sw::FORMAT_D16:            return 16;
+		case sw::FORMAT_D32F:
+		case sw::FORMAT_D32F_COMPLEMENTARY:
+		case sw::FORMAT_D32F_LOCKABLE:  return 32;
+		case sw::FORMAT_DF24S8:
+		case sw::FORMAT_D24FS8:         return 24;
+	//	case sw::FORMAT_D32_LOCKABLE:   return 32;
+	//	case sw::FORMAT_S8_LOCKABLE:    return 0;
+		case sw::FORMAT_D32FS8_SHADOW:
+		case sw::FORMAT_D32FS8_TEXTURE: return 32;
+		default:                        return 0;
+		}
+	}
+
+	GLenum GetComponentType(sw::Format format, GLenum attachment)
+	{
+		// Can be one of GL_FLOAT, GL_INT, GL_UNSIGNED_INT, GL_SIGNED_NORMALIZED, or GL_UNSIGNED_NORMALIZED
+		switch(attachment)
+		{
+		case GL_COLOR_ATTACHMENT0:
+		case GL_COLOR_ATTACHMENT1:
+		case GL_COLOR_ATTACHMENT2:
+		case GL_COLOR_ATTACHMENT3:
+		case GL_COLOR_ATTACHMENT4:
+		case GL_COLOR_ATTACHMENT5:
+		case GL_COLOR_ATTACHMENT6:
+		case GL_COLOR_ATTACHMENT7:
+		case GL_COLOR_ATTACHMENT8:
+		case GL_COLOR_ATTACHMENT9:
+		case GL_COLOR_ATTACHMENT10:
+		case GL_COLOR_ATTACHMENT11:
+		case GL_COLOR_ATTACHMENT12:
+		case GL_COLOR_ATTACHMENT13:
+		case GL_COLOR_ATTACHMENT14:
+		case GL_COLOR_ATTACHMENT15:
+		case GL_COLOR_ATTACHMENT16:
+		case GL_COLOR_ATTACHMENT17:
+		case GL_COLOR_ATTACHMENT18:
+		case GL_COLOR_ATTACHMENT19:
+		case GL_COLOR_ATTACHMENT20:
+		case GL_COLOR_ATTACHMENT21:
+		case GL_COLOR_ATTACHMENT22:
+		case GL_COLOR_ATTACHMENT23:
+		case GL_COLOR_ATTACHMENT24:
+		case GL_COLOR_ATTACHMENT25:
+		case GL_COLOR_ATTACHMENT26:
+		case GL_COLOR_ATTACHMENT27:
+		case GL_COLOR_ATTACHMENT28:
+		case GL_COLOR_ATTACHMENT29:
+		case GL_COLOR_ATTACHMENT30:
+		case GL_COLOR_ATTACHMENT31:
+			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_X32B32G32R32F:
+			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:
+			case sw::FORMAT_X8R8G8B8:
+			case sw::FORMAT_X8B8G8R8:
+			case sw::FORMAT_SRGB8_A8:
+			case sw::FORMAT_SRGB8_X8:
+			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;
+			}
+		case GL_DEPTH_ATTACHMENT:
+		case GL_STENCIL_ATTACHMENT:
+			// Only color buffers may have integer components.
+			return GL_FLOAT;
+		default:
+			UNREACHABLE(attachment);
+			return 0;
+		}
+	}
+
+	GLenum ConvertBackBufferFormat(sw::Format format)
+	{
+		switch(format)
+		{
+		case sw::FORMAT_A4R4G4B4: return GL_RGBA4;
+		case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES;
+		case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES;
+		case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1;
+		case sw::FORMAT_R5G6B5:   return GL_RGB565;
+		case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES;
+		case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES;
+		case sw::FORMAT_SRGB8_A8: return GL_RGBA8_OES;
+		case sw::FORMAT_SRGB8_X8: return GL_RGB8_OES;
+		default:
+			UNREACHABLE(format);
+		}
+
+		return GL_RGBA4;
+	}
+
+	GLenum ConvertDepthStencilFormat(sw::Format format)
+	{
+		switch(format)
+		{
+		case sw::FORMAT_D16:
+		case sw::FORMAT_D24X8:
+		case sw::FORMAT_D32:
+			return GL_DEPTH_COMPONENT16;
+		case sw::FORMAT_D24S8:
+			return GL_DEPTH24_STENCIL8_OES;
+		case sw::FORMAT_D32F:
+		case sw::FORMAT_D32F_COMPLEMENTARY:
+		case sw::FORMAT_D32F_LOCKABLE:
+			return GL_DEPTH_COMPONENT32F;
+		case sw::FORMAT_D32FS8_TEXTURE:
+		case sw::FORMAT_D32FS8_SHADOW:
+			return GL_DEPTH32F_STENCIL8;
+		case sw::FORMAT_S8:
+			return GL_STENCIL_INDEX8;
+		default:
+			UNREACHABLE(format);
+		}
+
+		return GL_DEPTH24_STENCIL8_OES;
+	}
+}