Added more OpenGL ES 3.0 cases in front end

- Added Texture2DArray where Texture3D was present
- Added OpenGL ES 3.0 compressed texture formats
- Used new buffer/texture parameters in setters/getters
- Added new Texture2D formats (mostly sized formats)
- Added missing matrix 2x3 code
- Added some trivial vertex attrib functions

Change-Id: I74913383a5623080a51193975d8b6bc811d06703
Reviewed-on: https://swiftshader-review.googlesource.com/2791
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index fe2744c..e5e4abf 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -494,6 +494,8 @@
 			return error(GL_INVALID_OPERATION);

 		}

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(target)

 		{

 		case GL_TEXTURE_2D:

@@ -505,6 +507,17 @@
 		case GL_TEXTURE_EXTERNAL_OES:

 			context->bindTextureExternal(texture);

 			return;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				context->bindTexture3D(texture);

+				break;

+			}

 		case GL_TEXTURE_3D_OES:

 			context->bindTexture3D(texture);

 			return;

@@ -684,12 +697,25 @@
 		return error(GL_INVALID_VALUE);

 	}

 

+	egl::GLint clientVersion = egl::getClientVersion();

+

 	switch(usage)

 	{

 	case GL_STREAM_DRAW:

 	case GL_STATIC_DRAW:

 	case GL_DYNAMIC_DRAW:

 		break;

+	case GL_STREAM_READ:

+	case GL_STREAM_COPY:

+	case GL_STATIC_READ:

+	case GL_STATIC_COPY:

+	case GL_DYNAMIC_READ:

+	case GL_DYNAMIC_COPY:

+		if(clientVersion < 3)

+		{

+			return error(GL_INVALID_ENUM);

+		}

+		break;

 	default:

 		return error(GL_INVALID_ENUM);

 	}

@@ -714,6 +740,7 @@
 

 		if(!buffer)

 		{

+			// A null buffer means that "0" is bound to the requested buffer target

 			return error(GL_INVALID_OPERATION);

 		}

 

@@ -759,6 +786,7 @@
 

 		if(!buffer)

 		{

+			// A null buffer means that "0" is bound to the requested buffer target

 			return error(GL_INVALID_OPERATION);

 		}

 

@@ -905,10 +933,27 @@
 		return error(GL_INVALID_VALUE);

 	}

 

+	egl::GLint clientVersion = egl::getClientVersion();

+

 	switch(internalformat)

 	{

 	case GL_ETC1_RGB8_OES:

 		break;

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

+		if(clientVersion >= 3)

+		{

+			break;

+		}

+		return error(GL_INVALID_ENUM);

 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

 	case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

@@ -1031,10 +1076,27 @@
 		return error(GL_INVALID_VALUE);

 	}

 

+	egl::GLint clientVersion = egl::getClientVersion();

+

 	switch(format)

 	{

 	case GL_ETC1_RGB8_OES:

 		break;

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

+		if(clientVersion >= 3)

+		{

+			break;

+		}

+		return error(GL_INVALID_ENUM);

 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:

 	case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:

@@ -1658,6 +1720,20 @@
 {

 	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);

 

+	switch(mode)

+	{

+	case GL_POINTS:

+	case GL_LINES:

+	case GL_LINE_LOOP:

+	case GL_LINE_STRIP:

+	case GL_TRIANGLES:

+	case GL_TRIANGLE_FAN:

+	case GL_TRIANGLE_STRIP:

+		break;

+	default:

+		return error(GL_INVALID_ENUM);

+	}

+

 	if(count < 0 || first < 0)

 	{

 		return error(GL_INVALID_VALUE);

@@ -1676,6 +1752,20 @@
 	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",

 	      mode, count, type, indices);

 

+	switch(mode)

+	{

+	case GL_POINTS:

+	case GL_LINES:

+	case GL_LINE_LOOP:

+	case GL_LINE_STRIP:

+	case GL_TRIANGLES:

+	case GL_TRIANGLE_FAN:

+	case GL_TRIANGLE_STRIP:

+		break;

+	default:

+		return error(GL_INVALID_ENUM);

+	}

+

 	if(count < 0)

 	{

 		return error(GL_INVALID_VALUE);

@@ -2005,7 +2095,9 @@
 

 	if(context)

 	{

-		es2::Texture *texture;

+		es2::Texture *texture = nullptr;

+

+		egl::GLint clientVersion = context->getClientVersion();

 

 		switch(target)

 		{

@@ -2015,6 +2107,20 @@
 		case GL_TEXTURE_CUBE_MAP:

 			texture = context->getTextureCubeMap();

 			break;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				texture = context->getTexture3D();

+				break;

+			}

+		case GL_TEXTURE_3D_OES:

+			texture = context->getTexture3D();

+			break;

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -2354,6 +2460,8 @@
 			return error(GL_INVALID_OPERATION);

 		}

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(pname)

 		{

 		case GL_BUFFER_USAGE:

@@ -2362,6 +2470,34 @@
 		case GL_BUFFER_SIZE:

 			*params = buffer->size();

 			break;

+		case GL_BUFFER_ACCESS_FLAGS:

+			if(clientVersion >= 3)

+			{

+				*params = buffer->access();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_BUFFER_MAPPED:

+			if(clientVersion >= 3)

+			{

+				*params = buffer->isMapped();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_BUFFER_MAP_LENGTH:

+			if(clientVersion >= 3)

+			{

+				*params = buffer->length();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_BUFFER_MAP_OFFSET:

+			if(clientVersion >= 3)

+			{

+				*params = buffer->offset();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -2621,10 +2757,7 @@
 

 				for(unsigned int i = 0; i < numParams; ++i)

 				{

-					if(boolParams[i] == GL_FALSE)

-						params[i] = 0;

-					else

-						params[i] = 1;

+					params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;

 				}

 

 				delete [] boolParams;

@@ -2640,7 +2773,7 @@
 				{

 					if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)

 					{

-						params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);

+						params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) * 0.5f);

 					}

 					else

 					{

@@ -3021,6 +3154,8 @@
 	{

 		es2::Texture *texture;

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(target)

 		{

 		case GL_TEXTURE_2D:

@@ -3032,6 +3167,20 @@
 		case GL_TEXTURE_EXTERNAL_OES:

 			texture = context->getTextureExternal();

 			break;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				texture = context->getTexture3D();

+				break;

+			}

+		case GL_TEXTURE_3D_OES:

+			texture = context->getTexture3D();

+			break;

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -3059,6 +3208,83 @@
 		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:

 			*params = (GLfloat)1;

 			break;

+		case GL_TEXTURE_BASE_LEVEL:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getBaseLevel();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_COMPARE_FUNC:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getCompareFunc();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_COMPARE_MODE:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getCompareMode();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_IMMUTABLE_FORMAT:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getImmutableFormat();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MAX_LEVEL:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getMaxLevel();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MAX_LOD:

+			if(clientVersion >= 3)

+			{

+				*params = texture->getMaxLOD();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MIN_LOD:

+			if(clientVersion >= 3)

+			{

+				*params = texture->getMinLOD();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_R:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getSwizzleR();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_G:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getSwizzleG();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_B:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getSwizzleB();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_A:

+			if(clientVersion >= 3)

+			{

+				*params = (GLfloat)texture->getSwizzleA();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -3075,6 +3301,8 @@
 	{

 		es2::Texture *texture;

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(target)

 		{

 		case GL_TEXTURE_2D:

@@ -3086,6 +3314,20 @@
 		case GL_TEXTURE_EXTERNAL_OES:

 			texture = context->getTextureExternal();

 			break;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				texture = context->getTexture3D();

+				break;

+			}

+		case GL_TEXTURE_3D_OES:

+			texture = context->getTexture3D();

+			break;

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -3113,6 +3355,83 @@
 		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:

 			*params = 1;

 			break;

+		case GL_TEXTURE_BASE_LEVEL:

+			if(clientVersion >= 3)

+			{

+				*params = texture->getBaseLevel();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_COMPARE_FUNC:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getCompareFunc();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_COMPARE_MODE:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getCompareMode();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_IMMUTABLE_FORMAT:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getImmutableFormat();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MAX_LEVEL:

+			if(clientVersion >= 3)

+			{

+				*params = texture->getMaxLevel();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MAX_LOD:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getMaxLOD();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_MIN_LOD:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getMinLOD();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_R:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getSwizzleR();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_G:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getSwizzleG();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_B:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getSwizzleB();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

+		case GL_TEXTURE_SWIZZLE_A:

+			if(clientVersion >= 3)

+			{

+				*params = (GLint)texture->getSwizzleA();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -3301,6 +3620,8 @@
 		}

 

 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);

+		

+		egl::GLint clientVersion = context->getClientVersion();

 

 		switch(pname)

 		{

@@ -3328,6 +3649,28 @@
 				params[i] = attribState.mCurrentValue[i];

 			}

 			break;

+		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

+			if(clientVersion >= 3)

+			{

+				switch(attribState.mType)

+				{

+				case GL_BYTE:

+				case GL_UNSIGNED_BYTE:

+				case GL_SHORT:

+				case GL_UNSIGNED_SHORT:

+				case GL_INT:

+				case GL_INT_2_10_10_10_REV:

+				case GL_UNSIGNED_INT:

+				case GL_FIXED:

+					*params = (GLfloat)GL_TRUE;

+					break;

+				default:

+					*params = (GLfloat)GL_FALSE;

+					break;

+				}

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default: return error(GL_INVALID_ENUM);

 		}

 	}

@@ -3348,6 +3691,8 @@
 

 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(pname)

 		{

 		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:

@@ -3375,6 +3720,28 @@
 				params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));

 			}

 			break;

+		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

+			if(clientVersion >= 3)

+			{

+				switch(attribState.mType)

+				{

+				case GL_BYTE:

+				case GL_UNSIGNED_BYTE:

+				case GL_SHORT:

+				case GL_UNSIGNED_SHORT:

+				case GL_INT:

+				case GL_INT_2_10_10_10_REV:

+				case GL_UNSIGNED_INT:

+				case GL_FIXED:

+					*params = GL_TRUE;

+					break;

+				default:

+					*params = GL_FALSE;

+					break;

+				}

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default: return error(GL_INVALID_ENUM);

 		}

 	}

@@ -3667,6 +4034,8 @@
 

 	if(context)

 	{

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(pname)

 		{

 		case GL_UNPACK_ALIGNMENT:

@@ -3683,6 +4052,20 @@
 			}

 			context->setPackAlignment(param);

 			break;

+		case GL_PACK_ROW_LENGTH:

+		case GL_PACK_SKIP_PIXELS:

+		case GL_PACK_SKIP_ROWS:

+		case GL_UNPACK_ROW_LENGTH:

+		case GL_UNPACK_IMAGE_HEIGHT:

+		case GL_UNPACK_SKIP_PIXELS:

+		case GL_UNPACK_SKIP_ROWS:

+		case GL_UNPACK_SKIP_IMAGES:

+			if(clientVersion >= 3)

+			{

+				UNIMPLEMENTED();

+				break;

+			}

+			else return error(GL_INVALID_ENUM);

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -4137,29 +4520,538 @@
 				return error(GL_INVALID_ENUM);

 			}

 			break;

-		case GL_RGB:

-			switch(type)

+		case GL_RED:

+			switch(internalformat)

 			{

-			case GL_UNSIGNED_BYTE:

-			case GL_UNSIGNED_SHORT_5_6_5:

-			case GL_FLOAT:

-			case GL_HALF_FLOAT_OES:

+			case GL_R8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R8_SNORM:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R16F:

+				switch(type)

+				{

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R32F:

+				switch(type)

+				{

+				case GL_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

 				break;

 			default:

-				return error(GL_INVALID_ENUM);

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RED_INTEGER:

+			switch(internalformat)

+			{

+			case GL_R8UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R8I:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R16UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R16I:

+				switch(type)

+				{

+				case GL_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R32UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R32I:

+				switch(type)

+				{

+				case GL_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RG_INTEGER:

+			switch(internalformat)

+			{

+			case GL_RG8UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG8I:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG16UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG16I:

+				switch(type)

+				{

+				case GL_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG32UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG32I:

+				switch(type)

+				{

+				case GL_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RGB_INTEGER:

+			switch(internalformat)

+			{

+			case GL_RGB8UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB8I:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB16UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB16I:

+				switch(type)

+				{

+				case GL_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB32UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB32I:

+				switch(type)

+				{

+				case GL_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RGBA_INTEGER:

+			switch(internalformat)

+			{

+			case GL_RGBA8UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA8I:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB10_A2UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT_2_10_10_10_REV:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA16UI:

+				switch(type)

+				{

+				case GL_UNSIGNED_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA16I:

+				switch(type)

+				{

+				case GL_SHORT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA32UI:

+				switch(type)

+				{

+				case GL_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA32I:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RG:

+			switch(internalformat)

+			{

+			case GL_RG8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG8_SNORM:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG16F:

+				switch(type)

+				{

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RG32F:

+				switch(type)

+				{

+				case GL_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_RGB:

+			switch(internalformat)

+			{

+			case GL_RGB:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+				case GL_UNSIGNED_SHORT_5_6_5:

+				case GL_FLOAT:

+				case GL_HALF_FLOAT_OES:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_SRGB8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB565:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+				case GL_UNSIGNED_SHORT_5_6_5:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB8_SNORM:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_R11F_G11F_B10F:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT_10F_11F_11F_REV:

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB9_E5:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT_5_9_9_9_REV:

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB16F:

+				switch(type)

+				{

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB32F:

+				switch(type)

+				{

+				case GL_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			default:

+				return error(GL_INVALID_VALUE);

 			}

 			break;

 		case GL_RGBA:

-			switch(type)

+			switch(internalformat)

 			{

-			case GL_UNSIGNED_BYTE:

-			case GL_UNSIGNED_SHORT_4_4_4_4:

-			case GL_UNSIGNED_SHORT_5_5_5_1:

-			case GL_FLOAT:

-			case GL_HALF_FLOAT_OES:

+			case GL_RGBA:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+				case GL_UNSIGNED_SHORT_4_4_4_4:

+				case GL_UNSIGNED_SHORT_5_5_5_1:

+				case GL_FLOAT:

+				case GL_HALF_FLOAT_OES:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_SRGB8_ALPHA8:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB5_A1:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+				case GL_UNSIGNED_SHORT_5_5_5_1:

+				case GL_UNSIGNED_INT_2_10_10_10_REV:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA8_SNORM:

+				switch(type)

+				{

+				case GL_BYTE:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA4:

+				switch(type)

+				{

+				case GL_UNSIGNED_BYTE:

+				case GL_UNSIGNED_SHORT_4_4_4_4:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGB10_A2:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT_2_10_10_10_REV:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA16F:

+				switch(type)

+				{

+				case GL_FLOAT:

+				case GL_HALF_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_RGBA32F:

+				switch(type)

+				{

+				case GL_FLOAT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

 				break;

 			default:

-				return error(GL_INVALID_ENUM);

+				return error(GL_INVALID_VALUE);

 			}

 			break;

 		case GL_BGRA_EXT:

@@ -4186,22 +5078,65 @@
 				return error(GL_INVALID_ENUM);

 			}

 		case GL_DEPTH_COMPONENT:

-			switch(type)

+			switch(internalformat)

 			{

-			case GL_UNSIGNED_SHORT:

-			case GL_UNSIGNED_INT:

+			case GL_DEPTH_COMPONENT:

+			case GL_DEPTH_COMPONENT16:

+				switch(type)

+				{

+				case GL_UNSIGNED_SHORT:

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_DEPTH_COMPONENT24:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_DEPTH_COMPONENT32F:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

 				break;

 			default:

-				return error(GL_INVALID_ENUM);

+				return error(GL_INVALID_VALUE);

 			}

 			break;

 		case GL_DEPTH_STENCIL_OES:

-			switch(type)

+			switch(internalformat)

 			{

-			case GL_UNSIGNED_INT_24_8_OES:

+			case GL_DEPTH_STENCIL_OES:

+			case GL_DEPTH24_STENCIL8:

+				switch(type)

+				{

+				case GL_UNSIGNED_INT_24_8_OES:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

+				break;

+			case GL_DEPTH32F_STENCIL8:

+				switch(type)

+				{

+				case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:

+					break;

+				default:

+					return error(GL_INVALID_ENUM);

+				}

 				break;

 			default:

-				return error(GL_INVALID_ENUM);

+				return error(GL_INVALID_VALUE);

 			}

 			break;

 		default:

@@ -4278,11 +5213,24 @@
 	{

 		es2::Texture *texture;

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(target)

 		{

 		case GL_TEXTURE_2D:

 			texture = context->getTexture2D();

 			break;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				texture = context->getTexture3D();

+				break;

+			}

 		case GL_TEXTURE_3D_OES:

 			texture = context->getTexture3D();

 			break;

@@ -4334,6 +5282,72 @@
 				return error(GL_INVALID_VALUE);

 			}

 			break;

+		case GL_TEXTURE_BASE_LEVEL:

+			if(clientVersion < 3 || !texture->setBaseLevel((GLint)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_COMPARE_FUNC:

+			if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_COMPARE_MODE:

+			if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_IMMUTABLE_FORMAT:

+			if(clientVersion < 3 || !texture->setCompareMode((GLboolean)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MAX_LEVEL:

+			if(clientVersion < 3 || !texture->setMaxLevel((GLint)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MAX_LOD:

+			if(clientVersion < 3 || !texture->setMaxLOD(param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MIN_LOD:

+			if(clientVersion < 3 || !texture->setMinLOD(param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_R:

+			if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_G:

+			if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_B:

+			if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_A:

+			if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -4355,11 +5369,24 @@
 	{

 		es2::Texture *texture;

 

+		egl::GLint clientVersion = context->getClientVersion();

+

 		switch(target)

 		{

 		case GL_TEXTURE_2D:

 			texture = context->getTexture2D();

 			break;

+		case GL_TEXTURE_2D_ARRAY:

+			if(clientVersion < 3)

+			{

+				return error(GL_INVALID_ENUM);

+			}

+			else

+			{

+				UNIMPLEMENTED();

+				texture = context->getTexture3D();

+				break;

+			}

 		case GL_TEXTURE_3D_OES:

 			texture = context->getTexture3D();

 			break;

@@ -4411,6 +5438,71 @@
 				return error(GL_INVALID_VALUE);

 			}

 			break;

+		case GL_TEXTURE_BASE_LEVEL:

+			if(clientVersion < 3 || !texture->setBaseLevel(param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_COMPARE_FUNC:

+			if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_COMPARE_MODE:

+			if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+		case GL_TEXTURE_IMMUTABLE_FORMAT:

+			if(clientVersion < 3 || !texture->setCompareMode((GLboolean)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MAX_LEVEL:

+			if(clientVersion < 3 || !texture->setMaxLevel(param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MAX_LOD:

+			if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_MIN_LOD:

+			if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_R:

+			if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_G:

+			if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_B:

+			if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

+		case GL_TEXTURE_SWIZZLE_A:

+			if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+			break;

 		default:

 			return error(GL_INVALID_ENUM);

 		}

@@ -5112,6 +6204,8 @@
 		return error(GL_INVALID_VALUE);

 	}

 

+	egl::GLint clientVersion = egl::getClientVersion();

+

 	switch(type)

 	{

 	case GL_BYTE:

@@ -5121,6 +6215,25 @@
 	case GL_FIXED:

 	case GL_FLOAT:

 		break;

+	case GL_INT_2_10_10_10_REV:

+	case GL_UNSIGNED_INT_2_10_10_10_REV:

+		if(clientVersion >= 3)

+		{

+			if(size != 4)

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+			break;

+		}

+		else return error(GL_INVALID_ENUM);

+	case GL_INT:

+	case GL_UNSIGNED_INT:

+	case GL_HALF_FLOAT:

+		if(clientVersion >= 3)

+		{

+			break;

+		}

+		else return error(GL_INVALID_ENUM);

 	default:

 		return error(GL_INVALID_ENUM);

 	}

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 2186bae..08b9149 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -11,6 +11,7 @@
 // libGLESv3.cpp: Implements the exported OpenGL ES 3.0 functions.

 

 #include "main.h"

+#include "Buffer.h"

 #include "Framebuffer.h"

 #include "Program.h"

 #include "Query.h"

@@ -938,7 +939,33 @@
 void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)

 {

 	TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);

-	UNIMPLEMENTED();

+

+	if(count < 0 || transpose != GL_FALSE)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	if(location == -1)

+	{

+		return;

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		es2::Program *program = context->getCurrentProgram();

+

+		if(!program)

+		{

+			return error(GL_INVALID_OPERATION);

+		}

+

+		if(!program->setUniformMatrix2x3fv(location, count, value))

+		{

+			return error(GL_INVALID_OPERATION);

+		}

+	}

 }

 

 void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)

@@ -1511,21 +1538,154 @@
 {

 	TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLsizei *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",

 	      index, size, type, stride, pointer);

-	UNIMPLEMENTED();

+

+	if(index >= es2::MAX_VERTEX_ATTRIBS)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	if(size < 1 || size > 4 || stride < 0)

+	{

+		return error(GL_INVALID_VALUE);

+	}

+

+	switch(type)

+	{

+	case GL_BYTE:

+	case GL_UNSIGNED_BYTE:

+	case GL_SHORT:

+	case GL_UNSIGNED_SHORT:

+	case GL_INT:

+	case GL_UNSIGNED_INT:

+		break;

+	default:

+		return error(GL_INVALID_ENUM);

+	}

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, stride, pointer);

+	}

 }

 

 void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)

 {

 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",

 	      index, pname, params);

-	UNIMPLEMENTED();

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		if(index >= es2::MAX_VERTEX_ATTRIBS)

+		{

+			return error(GL_INVALID_VALUE);

+		}

+

+		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);

+

+		switch(pname)

+		{

+		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:

+			*params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_SIZE:

+			*params = attribState.mSize;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:

+			*params = attribState.mStride;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_TYPE:

+			*params = attribState.mType;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:

+			*params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

+			*params = attribState.mBoundBuffer.name();

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

+			switch(attribState.mType)

+			{

+			case GL_BYTE:

+			case GL_UNSIGNED_BYTE:

+			case GL_SHORT:

+			case GL_UNSIGNED_SHORT:

+			case GL_INT:

+			case GL_INT_2_10_10_10_REV:

+			case GL_UNSIGNED_INT:

+			case GL_FIXED:

+				*params = GL_TRUE;

+				break;

+			default:

+				*params = GL_FALSE;

+				break;

+			}

+			break;

+		default: return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)

 {

 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)",

-	      index, pname, params);

-	UNIMPLEMENTED();

+		index, pname, params);

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		if(index >= es2::MAX_VERTEX_ATTRIBS)

+		{

+			return error(GL_INVALID_VALUE);

+		}

+

+		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);

+

+		switch(pname)

+		{

+		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:

+			*params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_SIZE:

+			*params = attribState.mSize;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:

+			*params = attribState.mStride;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_TYPE:

+			*params = attribState.mType;

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:

+			*params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:

+			*params = attribState.mBoundBuffer.name();

+			break;

+		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:

+			switch(attribState.mType)

+			{

+			case GL_BYTE:

+			case GL_UNSIGNED_BYTE:

+			case GL_SHORT:

+			case GL_UNSIGNED_SHORT:

+			case GL_INT:

+			case GL_INT_2_10_10_10_REV:

+			case GL_UNSIGNED_INT:

+			case GL_FIXED:

+				*params = GL_TRUE;

+				break;

+			default:

+				*params = GL_FALSE;

+				break;

+			}

+			break;

+		default: return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)

@@ -1558,7 +1718,33 @@
 {

 	TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = 0x%0.8p)",

 	      program, location, params);

-	UNIMPLEMENTED();

+

+	es2::Context *context = es2::getContext();

+

+	if(context)

+	{

+		if(program == 0)

+		{

+			return error(GL_INVALID_VALUE);

+		}

+

+		es2::Program *programObject = context->getProgram(program);

+

+		if(!programObject || !programObject->isLinked())

+		{

+			return error(GL_INVALID_OPERATION);

+		}

+

+		if(!programObject)

+		{

+			return error(GL_INVALID_OPERATION);

+		}

+

+		if(!programObject->getUniformuiv(location, NULL, params))

+		{

+			return error(GL_INVALID_OPERATION);

+		}

+	}

 }

 

 GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)

@@ -1908,9 +2094,9 @@
 

 	if(context)

 	{

-		es2::Program *program = context->getCurrentProgram();

+		es2::Program *programObject = context->getProgram(program);

 

-		if(!program)

+		if(!programObject)

 		{

 			return error(GL_INVALID_OPERATION);

 		}

@@ -1943,9 +2129,9 @@
 

 	if(context)

 	{

-		es2::Program *program = context->getCurrentProgram();

+		es2::Program *programObject = context->getProgram(program);

 

-		if(!program)

+		if(!programObject)

 		{

 			return error(GL_INVALID_OPERATION);

 		}

@@ -1963,9 +2149,9 @@
 

 	if(context)

 	{

-		es2::Program *program = context->getCurrentProgram();

+		es2::Program *programObject = context->getProgram(program);

 

-		if(!program)

+		if(!programObject)

 		{

 			return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);

 		}

@@ -2018,9 +2204,9 @@
 

 	if(context)

 	{

-		es2::Program *program = context->getCurrentProgram();

+		es2::Program *programObject = context->getProgram(program);

 

-		if(!program)

+		if(!programObject)

 		{

 			return error(GL_INVALID_OPERATION);

 		}

@@ -2038,11 +2224,11 @@
 

 	if(context)

 	{

-		es2::Program *program = context->getCurrentProgram();

+		es2::Program *programObject = context->getProgram(program);

 

-		if(!program)

+		if(!programObject)

 		{

-			return error(GL_INVALID_OPERATION);

+			return error(GL_INVALID_VALUE);

 		}

 	}