Home | History | Annotate | Download | only in libGLESv2
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
     15 
     16 #include "main.h"
     17 #include "mathutil.h"
     18 #include "utilities.h"
     19 #include "Buffer.h"
     20 #include "Context.h"
     21 #include "Fence.h"
     22 #include "Framebuffer.h"
     23 #include "Program.h"
     24 #include "Renderbuffer.h"
     25 #include "Shader.h"
     26 #include "Texture.h"
     27 #include "Query.h"
     28 #include "TransformFeedback.h"
     29 #include "common/debug.h"
     30 #include "Common/Version.h"
     31 
     32 #include <GLES2/gl2.h>
     33 #include <GLES2/gl2ext.h>
     34 #include <GLES3/gl3.h>
     35 
     36 #include <limits>
     37 
     38 #ifdef __ANDROID__
     39 #include <cutils/log.h>
     40 #endif
     41 
     42 namespace es2
     43 {
     44 
     45 static bool validImageSize(GLint level, GLsizei width, GLsizei height)
     46 {
     47 	if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
     48 	{
     49 		return false;
     50 	}
     51 
     52 	return true;
     53 }
     54 
     55 static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
     56 {
     57 	GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
     58 	if(validationError != GL_NONE)
     59 	{
     60 		return error(validationError, false);
     61 	}
     62 
     63 	// [OpenGL ES 2.0.24] table 3.9
     64 	switch(textureFormat)
     65 	{
     66 	case GL_ALPHA:
     67 		if(colorbufferFormat != GL_ALPHA &&
     68 		   colorbufferFormat != GL_RGBA &&
     69 		   colorbufferFormat != GL_RGBA4 &&
     70 		   colorbufferFormat != GL_RGB5_A1 &&
     71 		   colorbufferFormat != GL_RGBA8_OES &&
     72 		   colorbufferFormat != GL_BGRA8_EXT &&
     73 		   colorbufferFormat != GL_RGBA16F_EXT &&
     74 		   colorbufferFormat != GL_RGBA32F_EXT)
     75 		{
     76 			return error(GL_INVALID_OPERATION, false);
     77 		}
     78 		break;
     79 	case GL_LUMINANCE:
     80 	case GL_RGB:
     81 		if(colorbufferFormat != GL_RGB &&
     82 		   colorbufferFormat != GL_RGB565 &&
     83 		   colorbufferFormat != GL_RGB8_OES &&
     84 		   colorbufferFormat != GL_RGBA &&
     85 		   colorbufferFormat != GL_RGBA4 &&
     86 		   colorbufferFormat != GL_RGB5_A1 &&
     87 		   colorbufferFormat != GL_RGBA8_OES &&
     88 		   colorbufferFormat != GL_RGB16F_EXT &&
     89 		   colorbufferFormat != GL_RGB32F_EXT &&
     90 		   colorbufferFormat != GL_BGRA8_EXT &&
     91 		   colorbufferFormat != GL_RGBA16F_EXT &&
     92 		   colorbufferFormat != GL_RGBA32F_EXT)
     93 		{
     94 			return error(GL_INVALID_OPERATION, false);
     95 		}
     96 		break;
     97 	case GL_LUMINANCE_ALPHA:
     98 	case GL_RGBA:
     99 		if(colorbufferFormat != GL_RGBA &&
    100 		   colorbufferFormat != GL_RGBA4 &&
    101 		   colorbufferFormat != GL_RGB5_A1 &&
    102 		   colorbufferFormat != GL_RGBA8_OES &&
    103 		   colorbufferFormat != GL_BGRA8_EXT &&
    104 		   colorbufferFormat != GL_RGBA16F_EXT &&
    105 		   colorbufferFormat != GL_RGBA32F_EXT)
    106 		{
    107 			return error(GL_INVALID_OPERATION, false);
    108 		}
    109 		break;
    110 	case GL_DEPTH_COMPONENT:
    111 	case GL_DEPTH_STENCIL_OES:
    112 		return error(GL_INVALID_OPERATION, false);
    113 	default:
    114 		return error(GL_INVALID_ENUM, false);
    115 	}
    116 	return true;
    117 }
    118 
    119 void ActiveTexture(GLenum texture)
    120 {
    121 	TRACE("(GLenum texture = 0x%X)", texture);
    122 
    123 	es2::Context *context = es2::getContext();
    124 
    125 	if(context)
    126 	{
    127 		if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
    128 		{
    129 			return error(GL_INVALID_ENUM);
    130 		}
    131 
    132 		context->setActiveSampler(texture - GL_TEXTURE0);
    133 	}
    134 }
    135 
    136 void AttachShader(GLuint program, GLuint shader)
    137 {
    138 	TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
    139 
    140 	es2::Context *context = es2::getContext();
    141 
    142 	if(context)
    143 	{
    144 		es2::Program *programObject = context->getProgram(program);
    145 		es2::Shader *shaderObject = context->getShader(shader);
    146 
    147 		if(!programObject)
    148 		{
    149 			if(context->getShader(program))
    150 			{
    151 				return error(GL_INVALID_OPERATION);
    152 			}
    153 			else
    154 			{
    155 				return error(GL_INVALID_VALUE);
    156 			}
    157 		}
    158 
    159 		if(!shaderObject)
    160 		{
    161 			if(context->getProgram(shader))
    162 			{
    163 				return error(GL_INVALID_OPERATION);
    164 			}
    165 			else
    166 			{
    167 				return error(GL_INVALID_VALUE);
    168 			}
    169 		}
    170 
    171 		if(!programObject->attachShader(shaderObject))
    172 		{
    173 			return error(GL_INVALID_OPERATION);
    174 		}
    175 	}
    176 }
    177 
    178 void BeginQueryEXT(GLenum target, GLuint name)
    179 {
    180 	TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
    181 
    182 	switch(target)
    183 	{
    184 	case GL_ANY_SAMPLES_PASSED_EXT:
    185 	case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
    186 		break;
    187 	default:
    188 		return error(GL_INVALID_ENUM);
    189 	}
    190 
    191 	if(name == 0)
    192 	{
    193 		return error(GL_INVALID_OPERATION);
    194 	}
    195 
    196 	es2::Context *context = es2::getContext();
    197 
    198 	if(context)
    199 	{
    200 		context->beginQuery(target, name);
    201 	}
    202 }
    203 
    204 void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
    205 {
    206 	TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
    207 
    208 	if(index >= es2::MAX_VERTEX_ATTRIBS)
    209 	{
    210 		return error(GL_INVALID_VALUE);
    211 	}
    212 
    213 	es2::Context *context = es2::getContext();
    214 
    215 	if(context)
    216 	{
    217 		es2::Program *programObject = context->getProgram(program);
    218 
    219 		if(!programObject)
    220 		{
    221 			if(context->getShader(program))
    222 			{
    223 				return error(GL_INVALID_OPERATION);
    224 			}
    225 			else
    226 			{
    227 				return error(GL_INVALID_VALUE);
    228 			}
    229 		}
    230 
    231 		if(strncmp(name, "gl_", 3) == 0)
    232 		{
    233 			return error(GL_INVALID_OPERATION);
    234 		}
    235 
    236 		programObject->bindAttributeLocation(index, name);
    237 	}
    238 }
    239 
    240 void BindBuffer(GLenum target, GLuint buffer)
    241 {
    242 	TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
    243 
    244 	es2::Context *context = es2::getContext();
    245 
    246 	if(context)
    247 	{
    248 		GLint clientVersion = egl::getClientVersion();
    249 
    250 		switch(target)
    251 		{
    252 		case GL_ARRAY_BUFFER:
    253 			context->bindArrayBuffer(buffer);
    254 			return;
    255 		case GL_ELEMENT_ARRAY_BUFFER:
    256 			context->bindElementArrayBuffer(buffer);
    257 			return;
    258 		case GL_COPY_READ_BUFFER:
    259 			if(clientVersion >= 3)
    260 			{
    261 				context->bindCopyReadBuffer(buffer);
    262 				return;
    263 			}
    264 			else return error(GL_INVALID_ENUM);
    265 		case GL_COPY_WRITE_BUFFER:
    266 			if(clientVersion >= 3)
    267 			{
    268 				context->bindCopyWriteBuffer(buffer);
    269 				return;
    270 			}
    271 			else return error(GL_INVALID_ENUM);
    272 		case GL_PIXEL_PACK_BUFFER:
    273 			if(clientVersion >= 3)
    274 			{
    275 				context->bindPixelPackBuffer(buffer);
    276 				return;
    277 			}
    278 			else return error(GL_INVALID_ENUM);
    279 		case GL_PIXEL_UNPACK_BUFFER:
    280 			if(clientVersion >= 3)
    281 			{
    282 				context->bindPixelUnpackBuffer(buffer);
    283 				return;
    284 			}
    285 			else return error(GL_INVALID_ENUM);
    286 		case GL_TRANSFORM_FEEDBACK_BUFFER:
    287 			if(clientVersion >= 3)
    288 			{
    289 				context->bindTransformFeedbackBuffer(buffer);
    290 				return;
    291 			}
    292 			else return error(GL_INVALID_ENUM);
    293 		case GL_UNIFORM_BUFFER:
    294 			if(clientVersion >= 3)
    295 			{
    296 				context->bindGenericUniformBuffer(buffer);
    297 				return;
    298 			}
    299 			else return error(GL_INVALID_ENUM);
    300 		default:
    301 			return error(GL_INVALID_ENUM);
    302 		}
    303 	}
    304 }
    305 
    306 void BindFramebuffer(GLenum target, GLuint framebuffer)
    307 {
    308 	TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
    309 
    310 	if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
    311 	{
    312 		return error(GL_INVALID_ENUM);
    313 	}
    314 
    315 	es2::Context *context = es2::getContext();
    316 
    317 	if(context)
    318 	{
    319 		if(target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
    320 		{
    321 			context->bindReadFramebuffer(framebuffer);
    322 		}
    323 
    324 		if(target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
    325 		{
    326 			context->bindDrawFramebuffer(framebuffer);
    327 		}
    328 	}
    329 }
    330 
    331 void BindRenderbuffer(GLenum target, GLuint renderbuffer)
    332 {
    333 	TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
    334 
    335 	if(target != GL_RENDERBUFFER)
    336 	{
    337 		return error(GL_INVALID_ENUM);
    338 	}
    339 
    340 	es2::Context *context = es2::getContext();
    341 
    342 	if(context)
    343 	{
    344 		// [OpenGL ES 2.0.25] Section 4.4.3 page 110
    345 		// [OpenGL ES 3.0.4] Section 4.4.2 page 204
    346 		// If renderbuffer is not zero, then the resulting renderbuffer object
    347 		// is a new state vector, initialized with a zero-sized memory buffer.
    348 		context->bindRenderbuffer(renderbuffer);
    349 	}
    350 }
    351 
    352 void BindTexture(GLenum target, GLuint texture)
    353 {
    354 	TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
    355 
    356 	es2::Context *context = es2::getContext();
    357 
    358 	if(context)
    359 	{
    360 		es2::Texture *textureObject = context->getTexture(texture);
    361 
    362 		if(textureObject && textureObject->getTarget() != target && texture != 0)
    363 		{
    364 			return error(GL_INVALID_OPERATION);
    365 		}
    366 
    367 		GLint clientVersion = context->getClientVersion();
    368 
    369 		switch(target)
    370 		{
    371 		case GL_TEXTURE_2D:
    372 			context->bindTexture2D(texture);
    373 			break;
    374 		case GL_TEXTURE_CUBE_MAP:
    375 			context->bindTextureCubeMap(texture);
    376 			break;
    377 		case GL_TEXTURE_EXTERNAL_OES:
    378 			context->bindTextureExternal(texture);
    379 			break;
    380 		case GL_TEXTURE_2D_ARRAY:
    381 			if(clientVersion < 3)
    382 			{
    383 				return error(GL_INVALID_ENUM);
    384 			}
    385 			context->bindTexture2DArray(texture);
    386 			break;
    387 		case GL_TEXTURE_3D_OES:
    388 			context->bindTexture3D(texture);
    389 			break;
    390 		default:
    391 			return error(GL_INVALID_ENUM);
    392 		}
    393 	}
    394 }
    395 
    396 void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
    397 {
    398 	TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
    399 		red, green, blue, alpha);
    400 
    401 	es2::Context* context = es2::getContext();
    402 
    403 	if(context)
    404 	{
    405 		context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
    406 	}
    407 }
    408 
    409 void BlendEquation(GLenum mode)
    410 {
    411 	glBlendEquationSeparate(mode, mode);
    412 }
    413 
    414 void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
    415 {
    416 	TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
    417 
    418 	switch(modeRGB)
    419 	{
    420 	case GL_FUNC_ADD:
    421 	case GL_FUNC_SUBTRACT:
    422 	case GL_FUNC_REVERSE_SUBTRACT:
    423 	case GL_MIN_EXT:
    424 	case GL_MAX_EXT:
    425 		break;
    426 	default:
    427 		return error(GL_INVALID_ENUM);
    428 	}
    429 
    430 	switch(modeAlpha)
    431 	{
    432 	case GL_FUNC_ADD:
    433 	case GL_FUNC_SUBTRACT:
    434 	case GL_FUNC_REVERSE_SUBTRACT:
    435 	case GL_MIN_EXT:
    436 	case GL_MAX_EXT:
    437 		break;
    438 	default:
    439 		return error(GL_INVALID_ENUM);
    440 	}
    441 
    442 	es2::Context *context = es2::getContext();
    443 
    444 	if(context)
    445 	{
    446 		context->setBlendEquation(modeRGB, modeAlpha);
    447 	}
    448 }
    449 
    450 void BlendFunc(GLenum sfactor, GLenum dfactor)
    451 {
    452 	glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
    453 }
    454 
    455 void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
    456 {
    457 	TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
    458 	      srcRGB, dstRGB, srcAlpha, dstAlpha);
    459 
    460 	GLint clientVersion = egl::getClientVersion();
    461 
    462 	switch(srcRGB)
    463 	{
    464 	case GL_ZERO:
    465 	case GL_ONE:
    466 	case GL_SRC_COLOR:
    467 	case GL_ONE_MINUS_SRC_COLOR:
    468 	case GL_DST_COLOR:
    469 	case GL_ONE_MINUS_DST_COLOR:
    470 	case GL_SRC_ALPHA:
    471 	case GL_ONE_MINUS_SRC_ALPHA:
    472 	case GL_DST_ALPHA:
    473 	case GL_ONE_MINUS_DST_ALPHA:
    474 	case GL_CONSTANT_COLOR:
    475 	case GL_ONE_MINUS_CONSTANT_COLOR:
    476 	case GL_CONSTANT_ALPHA:
    477 	case GL_ONE_MINUS_CONSTANT_ALPHA:
    478 	case GL_SRC_ALPHA_SATURATE:
    479 		break;
    480 	default:
    481 		return error(GL_INVALID_ENUM);
    482 	}
    483 
    484 	switch(dstRGB)
    485 	{
    486 	case GL_ZERO:
    487 	case GL_ONE:
    488 	case GL_SRC_COLOR:
    489 	case GL_ONE_MINUS_SRC_COLOR:
    490 	case GL_DST_COLOR:
    491 	case GL_ONE_MINUS_DST_COLOR:
    492 	case GL_SRC_ALPHA:
    493 	case GL_ONE_MINUS_SRC_ALPHA:
    494 	case GL_DST_ALPHA:
    495 	case GL_ONE_MINUS_DST_ALPHA:
    496 	case GL_CONSTANT_COLOR:
    497 	case GL_ONE_MINUS_CONSTANT_COLOR:
    498 	case GL_CONSTANT_ALPHA:
    499 	case GL_ONE_MINUS_CONSTANT_ALPHA:
    500 		break;
    501 	case GL_SRC_ALPHA_SATURATE:
    502 		if(clientVersion < 3)
    503 		{
    504 			return error(GL_INVALID_ENUM);
    505 		}
    506 		break;
    507 	default:
    508 		return error(GL_INVALID_ENUM);
    509 	}
    510 
    511 	switch(srcAlpha)
    512 	{
    513 	case GL_ZERO:
    514 	case GL_ONE:
    515 	case GL_SRC_COLOR:
    516 	case GL_ONE_MINUS_SRC_COLOR:
    517 	case GL_DST_COLOR:
    518 	case GL_ONE_MINUS_DST_COLOR:
    519 	case GL_SRC_ALPHA:
    520 	case GL_ONE_MINUS_SRC_ALPHA:
    521 	case GL_DST_ALPHA:
    522 	case GL_ONE_MINUS_DST_ALPHA:
    523 	case GL_CONSTANT_COLOR:
    524 	case GL_ONE_MINUS_CONSTANT_COLOR:
    525 	case GL_CONSTANT_ALPHA:
    526 	case GL_ONE_MINUS_CONSTANT_ALPHA:
    527 	case GL_SRC_ALPHA_SATURATE:
    528 		break;
    529 	default:
    530 		return error(GL_INVALID_ENUM);
    531 	}
    532 
    533 	switch(dstAlpha)
    534 	{
    535 	case GL_ZERO:
    536 	case GL_ONE:
    537 	case GL_SRC_COLOR:
    538 	case GL_ONE_MINUS_SRC_COLOR:
    539 	case GL_DST_COLOR:
    540 	case GL_ONE_MINUS_DST_COLOR:
    541 	case GL_SRC_ALPHA:
    542 	case GL_ONE_MINUS_SRC_ALPHA:
    543 	case GL_DST_ALPHA:
    544 	case GL_ONE_MINUS_DST_ALPHA:
    545 	case GL_CONSTANT_COLOR:
    546 	case GL_ONE_MINUS_CONSTANT_COLOR:
    547 	case GL_CONSTANT_ALPHA:
    548 	case GL_ONE_MINUS_CONSTANT_ALPHA:
    549 		break;
    550 	case GL_SRC_ALPHA_SATURATE:
    551 		if(clientVersion < 3)
    552 		{
    553 			return error(GL_INVALID_ENUM);
    554 		}
    555 		break;
    556 	default:
    557 		return error(GL_INVALID_ENUM);
    558 	}
    559 
    560 	es2::Context *context = es2::getContext();
    561 
    562 	if(context)
    563 	{
    564 		context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
    565 	}
    566 }
    567 
    568 void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
    569 {
    570 	size = static_cast<GLint>(size);   // Work around issues with some 64-bit applications
    571 
    572 	TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
    573 	      target, size, data, usage);
    574 
    575 	if(size < 0)
    576 	{
    577 		return error(GL_INVALID_VALUE);
    578 	}
    579 
    580 	GLint clientVersion = egl::getClientVersion();
    581 
    582 	switch(usage)
    583 	{
    584 	case GL_STREAM_DRAW:
    585 	case GL_STATIC_DRAW:
    586 	case GL_DYNAMIC_DRAW:
    587 		break;
    588 	case GL_STREAM_READ:
    589 	case GL_STREAM_COPY:
    590 	case GL_STATIC_READ:
    591 	case GL_STATIC_COPY:
    592 	case GL_DYNAMIC_READ:
    593 	case GL_DYNAMIC_COPY:
    594 		if(clientVersion < 3)
    595 		{
    596 			return error(GL_INVALID_ENUM);
    597 		}
    598 		break;
    599 	default:
    600 		return error(GL_INVALID_ENUM);
    601 	}
    602 
    603 	es2::Context *context = es2::getContext();
    604 
    605 	if(context)
    606 	{
    607 		es2::Buffer *buffer = nullptr;
    608 		if(!context->getBuffer(target, &buffer))
    609 		{
    610 			return error(GL_INVALID_ENUM);
    611 		}
    612 
    613 		if(!buffer)
    614 		{
    615 			// A null buffer means that "0" is bound to the requested buffer target
    616 			return error(GL_INVALID_OPERATION);
    617 		}
    618 
    619 		buffer->bufferData(data, size, usage);
    620 	}
    621 }
    622 
    623 void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
    624 {
    625 	size = static_cast<GLint>(size);   // Work around issues with some 64-bit applications
    626 	offset = static_cast<GLint>(offset);
    627 
    628 	TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
    629 	      target, offset, size, data);
    630 
    631 	if(size < 0 || offset < 0)
    632 	{
    633 		return error(GL_INVALID_VALUE);
    634 	}
    635 
    636 	es2::Context *context = es2::getContext();
    637 
    638 	if(context)
    639 	{
    640 		es2::Buffer *buffer = nullptr;
    641 		if(!context->getBuffer(target, &buffer))
    642 		{
    643 			return error(GL_INVALID_ENUM);
    644 		}
    645 
    646 		if(!buffer)
    647 		{
    648 			// A null buffer means that "0" is bound to the requested buffer target
    649 			return error(GL_INVALID_OPERATION);
    650 		}
    651 
    652 		if((size_t)size + offset > buffer->size())
    653 		{
    654 			return error(GL_INVALID_VALUE);
    655 		}
    656 
    657 		buffer->bufferSubData(data, size, offset);
    658 	}
    659 }
    660 
    661 GLenum CheckFramebufferStatus(GLenum target)
    662 {
    663 	TRACE("(GLenum target = 0x%X)", target);
    664 
    665 	if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
    666 	{
    667 		return error(GL_INVALID_ENUM, 0);
    668 	}
    669 
    670 	es2::Context *context = es2::getContext();
    671 
    672 	if(context)
    673 	{
    674 		es2::Framebuffer *framebuffer = nullptr;
    675 		if(target == GL_READ_FRAMEBUFFER_ANGLE)
    676 		{
    677 			framebuffer = context->getReadFramebuffer();
    678 		}
    679 		else
    680 		{
    681 			framebuffer = context->getDrawFramebuffer();
    682 		}
    683 
    684 		return framebuffer->completeness();
    685 	}
    686 
    687 	return 0;
    688 }
    689 
    690 void Clear(GLbitfield mask)
    691 {
    692 	TRACE("(GLbitfield mask = %X)", mask);
    693 
    694 	if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
    695 	{
    696 		return error(GL_INVALID_VALUE);
    697 	}
    698 
    699 	es2::Context *context = es2::getContext();
    700 
    701 	if(context)
    702 	{
    703 		context->clear(mask);
    704 	}
    705 }
    706 
    707 void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
    708 {
    709 	TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
    710 	      red, green, blue, alpha);
    711 
    712 	es2::Context *context = es2::getContext();
    713 
    714 	if(context)
    715 	{
    716 		context->setClearColor(red, green, blue, alpha);
    717 	}
    718 }
    719 
    720 void ClearDepthf(GLclampf depth)
    721 {
    722 	TRACE("(GLclampf depth = %f)", depth);
    723 
    724 	es2::Context *context = es2::getContext();
    725 
    726 	if(context)
    727 	{
    728 		context->setClearDepth(depth);
    729 	}
    730 }
    731 
    732 void ClearStencil(GLint s)
    733 {
    734 	TRACE("(GLint s = %d)", s);
    735 
    736 	es2::Context *context = es2::getContext();
    737 
    738 	if(context)
    739 	{
    740 		context->setClearStencil(s);
    741 	}
    742 }
    743 
    744 void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
    745 {
    746 	TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
    747 	      red, green, blue, alpha);
    748 
    749 	es2::Context *context = es2::getContext();
    750 
    751 	if(context)
    752 	{
    753 		context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
    754 	}
    755 }
    756 
    757 void CompileShader(GLuint shader)
    758 {
    759 	TRACE("(GLuint shader = %d)", shader);
    760 
    761 	es2::Context *context = es2::getContext();
    762 
    763 	if(context)
    764 	{
    765 		es2::Shader *shaderObject = context->getShader(shader);
    766 
    767 		if(!shaderObject)
    768 		{
    769 			if(context->getProgram(shader))
    770 			{
    771 				return error(GL_INVALID_OPERATION);
    772 			}
    773 			else
    774 			{
    775 				return error(GL_INVALID_VALUE);
    776 			}
    777 		}
    778 
    779 		shaderObject->compile();
    780 	}
    781 }
    782 
    783 void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
    784                           GLint border, GLsizei imageSize, const GLvoid* data)
    785 {
    786 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
    787 	      "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
    788 	      target, level, internalformat, width, height, border, imageSize, data);
    789 
    790 	if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
    791 	{
    792 		return error(GL_INVALID_VALUE);
    793 	}
    794 
    795 	switch(internalformat)
    796 	{
    797 	case GL_DEPTH_COMPONENT:
    798 	case GL_DEPTH_COMPONENT16:
    799 	case GL_DEPTH_COMPONENT32_OES:
    800 	case GL_DEPTH_STENCIL_OES:
    801 	case GL_DEPTH24_STENCIL8_OES:
    802 		return error(GL_INVALID_OPERATION);
    803 	default:
    804 		{
    805 			GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
    806 			if(validationError != GL_NONE)
    807 			{
    808 				return error(validationError);
    809 			}
    810 		}
    811 		break;
    812 	}
    813 
    814 	if(border != 0)
    815 	{
    816 		return error(GL_INVALID_VALUE);
    817 	}
    818 
    819 	es2::Context *context = es2::getContext();
    820 
    821 	if(context)
    822 	{
    823 		if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    824 		{
    825 			return error(GL_INVALID_VALUE);
    826 		}
    827 
    828 		switch(target)
    829 		{
    830 		case GL_TEXTURE_2D:
    831 			if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
    832 			   height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
    833 			{
    834 				return error(GL_INVALID_VALUE);
    835 			}
    836 			break;
    837 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    838 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    839 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    840 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    841 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    842 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    843 			if(width != height)
    844 			{
    845 				return error(GL_INVALID_VALUE);
    846 			}
    847 
    848 			if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
    849 			   height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
    850 			{
    851 				return error(GL_INVALID_VALUE);
    852 			}
    853 			break;
    854 		default:
    855 			return error(GL_INVALID_ENUM);
    856 		}
    857 
    858 		if(imageSize != egl::ComputeCompressedSize(width, height, internalformat))
    859 		{
    860 			return error(GL_INVALID_VALUE);
    861 		}
    862 
    863 		if(target == GL_TEXTURE_2D)
    864 		{
    865 			es2::Texture2D *texture = context->getTexture2D();
    866 
    867 			if(!texture)
    868 			{
    869 				return error(GL_INVALID_OPERATION);
    870 			}
    871 
    872 			texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
    873 		}
    874 		else
    875 		{
    876 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
    877 
    878 			if(!texture)
    879 			{
    880 				return error(GL_INVALID_OPERATION);
    881 			}
    882 
    883 			switch(target)
    884 			{
    885 			case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    886 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    887 			case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    888 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    889 			case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    890 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    891 				texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
    892 				break;
    893 			default: UNREACHABLE(target);
    894 			}
    895 		}
    896 	}
    897 }
    898 
    899 void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
    900                              GLenum format, GLsizei imageSize, const GLvoid* data)
    901 {
    902 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
    903 	      "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
    904 	      "GLsizei imageSize = %d, const GLvoid* data = %p)",
    905 	      target, level, xoffset, yoffset, width, height, format, imageSize, data);
    906 
    907 	if(!es2::IsTextureTarget(target))
    908 	{
    909 		return error(GL_INVALID_ENUM);
    910 	}
    911 
    912 	if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    913 	{
    914 		return error(GL_INVALID_VALUE);
    915 	}
    916 
    917 	if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
    918 	{
    919 		return error(GL_INVALID_VALUE);
    920 	}
    921 
    922 	GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
    923 	if(validationError != GL_NONE)
    924 	{
    925 		return error(validationError);
    926 	}
    927 
    928 	if(width == 0 || height == 0 || !data)
    929 	{
    930 		return;
    931 	}
    932 
    933 	es2::Context *context = es2::getContext();
    934 
    935 	if(context)
    936 	{
    937 		if(imageSize != egl::ComputeCompressedSize(width, height, format))
    938 		{
    939 			return error(GL_INVALID_VALUE);
    940 		}
    941 
    942 		if(xoffset % 4 != 0 || yoffset % 4 != 0)
    943 		{
    944 			// We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
    945 			return error(GL_INVALID_OPERATION);
    946 		}
    947 
    948 		GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_NONE);
    949 
    950 		if(target == GL_TEXTURE_2D)
    951 		{
    952 			es2::Texture2D *texture = context->getTexture2D();
    953 
    954 			GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
    955 
    956 			if(validationError == GL_NONE)
    957 			{
    958 				texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, context->getPixels(data));
    959 			}
    960 			else
    961 			{
    962 				return error(validationError);
    963 			}
    964 		}
    965 		else if(es2::IsCubemapTextureTarget(target))
    966 		{
    967 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
    968 
    969 			GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
    970 
    971 			if(validationError == GL_NONE)
    972 			{
    973 				texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, context->getPixels(data));
    974 			}
    975 			else
    976 			{
    977 				return error(validationError);
    978 			}
    979 		}
    980 		else UNREACHABLE(target);
    981 	}
    982 }
    983 
    984 void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
    985 {
    986 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
    987 	      "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
    988 	      target, level, internalformat, x, y, width, height, border);
    989 
    990 	if(!validImageSize(level, width, height))
    991 	{
    992 		return error(GL_INVALID_VALUE);
    993 	}
    994 
    995 	if(border != 0)
    996 	{
    997 		return error(GL_INVALID_VALUE);
    998 	}
    999 
   1000 	es2::Context *context = es2::getContext();
   1001 
   1002 	if(context)
   1003 	{
   1004 		switch(target)
   1005 		{
   1006 		case GL_TEXTURE_2D:
   1007 			if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
   1008 			   height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
   1009 			{
   1010 				return error(GL_INVALID_VALUE);
   1011 			}
   1012 			break;
   1013 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   1014 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   1015 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   1016 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   1017 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   1018 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   1019 			if(width != height)
   1020 			{
   1021 				return error(GL_INVALID_VALUE);
   1022 			}
   1023 
   1024 			if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
   1025 			   height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
   1026 			{
   1027 				return error(GL_INVALID_VALUE);
   1028 			}
   1029 			break;
   1030 		default:
   1031 			return error(GL_INVALID_ENUM);
   1032 		}
   1033 
   1034 		es2::Framebuffer *framebuffer = context->getReadFramebuffer();
   1035 
   1036 		if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
   1037 		{
   1038 			return error(GL_INVALID_FRAMEBUFFER_OPERATION);
   1039 		}
   1040 
   1041 		es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
   1042 
   1043 		if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
   1044 		{
   1045 			return error(GL_INVALID_OPERATION);
   1046 		}
   1047 
   1048 		GLenum colorbufferFormat = source->getFormat();
   1049 
   1050 		if(!validateColorBufferFormat(internalformat, colorbufferFormat))
   1051 		{
   1052 			return;
   1053 		}
   1054 
   1055 		if(target == GL_TEXTURE_2D)
   1056 		{
   1057 			es2::Texture2D *texture = context->getTexture2D();
   1058 
   1059 			if(!texture)
   1060 			{
   1061 				return error(GL_INVALID_OPERATION);
   1062 			}
   1063 
   1064 			texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
   1065 		}
   1066 		else if(es2::IsCubemapTextureTarget(target))
   1067 		{
   1068 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
   1069 
   1070 			if(!texture)
   1071 			{
   1072 				return error(GL_INVALID_OPERATION);
   1073 			}
   1074 
   1075 			texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
   1076 		}
   1077 		else UNREACHABLE(target);
   1078 	}
   1079 }
   1080 
   1081 void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
   1082 {
   1083 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
   1084 	      "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
   1085 	      target, level, xoffset, yoffset, x, y, width, height);
   1086 
   1087 	if(!es2::IsTextureTarget(target))
   1088 	{
   1089 		return error(GL_INVALID_ENUM);
   1090 	}
   1091 
   1092 	if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   1093 	{
   1094 		return error(GL_INVALID_VALUE);
   1095 	}
   1096 
   1097 	if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
   1098 	{
   1099 		return error(GL_INVALID_VALUE);
   1100 	}
   1101 
   1102 	if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
   1103 	{
   1104 		return error(GL_INVALID_VALUE);
   1105 	}
   1106 
   1107 	if(width == 0 || height == 0)
   1108 	{
   1109 		return;
   1110 	}
   1111 
   1112 	es2::Context *context = es2::getContext();
   1113 
   1114 	if(context)
   1115 	{
   1116 		es2::Framebuffer *framebuffer = context->getReadFramebuffer();
   1117 
   1118 		if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
   1119 		{
   1120 			return error(GL_INVALID_FRAMEBUFFER_OPERATION);
   1121 		}
   1122 
   1123 		es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
   1124 
   1125 		if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
   1126 		{
   1127 			return error(GL_INVALID_OPERATION);
   1128 		}
   1129 
   1130 		es2::Texture *texture = nullptr;
   1131 
   1132 		if(target == GL_TEXTURE_2D)
   1133 		{
   1134 			texture = context->getTexture2D();
   1135 		}
   1136 		else if(es2::IsCubemapTextureTarget(target))
   1137 		{
   1138 			texture = context->getTextureCubeMap();
   1139 		}
   1140 		else UNREACHABLE(target);
   1141 
   1142 		GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture);
   1143 		if(validationError != GL_NONE)
   1144 		{
   1145 			return error(validationError);
   1146 		}
   1147 
   1148 		texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
   1149 	}
   1150 }
   1151 
   1152 GLuint CreateProgram(void)
   1153 {
   1154 	TRACE("()");
   1155 
   1156 	es2::Context *context = es2::getContext();
   1157 
   1158 	if(context)
   1159 	{
   1160 		return context->createProgram();
   1161 	}
   1162 
   1163 	return 0;
   1164 }
   1165 
   1166 GLuint CreateShader(GLenum type)
   1167 {
   1168 	TRACE("(GLenum type = 0x%X)", type);
   1169 
   1170 	es2::Context *context = es2::getContext();
   1171 
   1172 	if(context)
   1173 	{
   1174 		switch(type)
   1175 		{
   1176 		case GL_FRAGMENT_SHADER:
   1177 		case GL_VERTEX_SHADER:
   1178 			return context->createShader(type);
   1179 		default:
   1180 			return error(GL_INVALID_ENUM, 0);
   1181 		}
   1182 	}
   1183 
   1184 	return 0;
   1185 }
   1186 
   1187 void CullFace(GLenum mode)
   1188 {
   1189 	TRACE("(GLenum mode = 0x%X)", mode);
   1190 
   1191 	switch(mode)
   1192 	{
   1193 	case GL_FRONT:
   1194 	case GL_BACK:
   1195 	case GL_FRONT_AND_BACK:
   1196 		{
   1197 			es2::Context *context = es2::getContext();
   1198 
   1199 			if(context)
   1200 			{
   1201 				context->setCullMode(mode);
   1202 			}
   1203 		}
   1204 		break;
   1205 	default:
   1206 		return error(GL_INVALID_ENUM);
   1207 	}
   1208 }
   1209 
   1210 void DeleteBuffers(GLsizei n, const GLuint* buffers)
   1211 {
   1212 	TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
   1213 
   1214 	if(n < 0)
   1215 	{
   1216 		return error(GL_INVALID_VALUE);
   1217 	}
   1218 
   1219 	es2::Context *context = es2::getContext();
   1220 
   1221 	if(context)
   1222 	{
   1223 		for(int i = 0; i < n; i++)
   1224 		{
   1225 			context->deleteBuffer(buffers[i]);
   1226 		}
   1227 	}
   1228 }
   1229 
   1230 void DeleteFencesNV(GLsizei n, const GLuint* fences)
   1231 {
   1232 	TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
   1233 
   1234 	if(n < 0)
   1235 	{
   1236 		return error(GL_INVALID_VALUE);
   1237 	}
   1238 
   1239 	es2::Context *context = es2::getContext();
   1240 
   1241 	if(context)
   1242 	{
   1243 		for(int i = 0; i < n; i++)
   1244 		{
   1245 			context->deleteFence(fences[i]);
   1246 		}
   1247 	}
   1248 }
   1249 
   1250 void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
   1251 {
   1252 	TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
   1253 
   1254 	if(n < 0)
   1255 	{
   1256 		return error(GL_INVALID_VALUE);
   1257 	}
   1258 
   1259 	es2::Context *context = es2::getContext();
   1260 
   1261 	if(context)
   1262 	{
   1263 		for(int i = 0; i < n; i++)
   1264 		{
   1265 			if(framebuffers[i] != 0)
   1266 			{
   1267 				context->deleteFramebuffer(framebuffers[i]);
   1268 			}
   1269 		}
   1270 	}
   1271 }
   1272 
   1273 void DeleteProgram(GLuint program)
   1274 {
   1275 	TRACE("(GLuint program = %d)", program);
   1276 
   1277 	if(program == 0)
   1278 	{
   1279 		return;
   1280 	}
   1281 
   1282 	es2::Context *context = es2::getContext();
   1283 
   1284 	if(context)
   1285 	{
   1286 		if(!context->getProgram(program))
   1287 		{
   1288 			if(context->getShader(program))
   1289 			{
   1290 				return error(GL_INVALID_OPERATION);
   1291 			}
   1292 			else
   1293 			{
   1294 				return error(GL_INVALID_VALUE);
   1295 			}
   1296 		}
   1297 
   1298 		context->deleteProgram(program);
   1299 	}
   1300 }
   1301 
   1302 void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
   1303 {
   1304 	TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
   1305 
   1306 	if(n < 0)
   1307 	{
   1308 		return error(GL_INVALID_VALUE);
   1309 	}
   1310 
   1311 	es2::Context *context = es2::getContext();
   1312 
   1313 	if(context)
   1314 	{
   1315 		for(int i = 0; i < n; i++)
   1316 		{
   1317 			context->deleteQuery(ids[i]);
   1318 		}
   1319 	}
   1320 }
   1321 
   1322 void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
   1323 {
   1324 	TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
   1325 
   1326 	if(n < 0)
   1327 	{
   1328 		return error(GL_INVALID_VALUE);
   1329 	}
   1330 
   1331 	es2::Context *context = es2::getContext();
   1332 
   1333 	if(context)
   1334 	{
   1335 		for(int i = 0; i < n; i++)
   1336 		{
   1337 			context->deleteRenderbuffer(renderbuffers[i]);
   1338 		}
   1339 	}
   1340 }
   1341 
   1342 void DeleteShader(GLuint shader)
   1343 {
   1344 	TRACE("(GLuint shader = %d)", shader);
   1345 
   1346 	if(shader == 0)
   1347 	{
   1348 		return;
   1349 	}
   1350 
   1351 	es2::Context *context = es2::getContext();
   1352 
   1353 	if(context)
   1354 	{
   1355 		if(!context->getShader(shader))
   1356 		{
   1357 			if(context->getProgram(shader))
   1358 			{
   1359 				return error(GL_INVALID_OPERATION);
   1360 			}
   1361 			else
   1362 			{
   1363 				return error(GL_INVALID_VALUE);
   1364 			}
   1365 		}
   1366 
   1367 		context->deleteShader(shader);
   1368 	}
   1369 }
   1370 
   1371 void DeleteTextures(GLsizei n, const GLuint* textures)
   1372 {
   1373 	TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
   1374 
   1375 	if(n < 0)
   1376 	{
   1377 		return error(GL_INVALID_VALUE);
   1378 	}
   1379 
   1380 	es2::Context *context = es2::getContext();
   1381 
   1382 	if(context)
   1383 	{
   1384 		for(int i = 0; i < n; i++)
   1385 		{
   1386 			if(textures[i] != 0)
   1387 			{
   1388 				context->deleteTexture(textures[i]);
   1389 			}
   1390 		}
   1391 	}
   1392 }
   1393 
   1394 void DepthFunc(GLenum func)
   1395 {
   1396 	TRACE("(GLenum func = 0x%X)", func);
   1397 
   1398 	switch(func)
   1399 	{
   1400 	case GL_NEVER:
   1401 	case GL_ALWAYS:
   1402 	case GL_LESS:
   1403 	case GL_LEQUAL:
   1404 	case GL_EQUAL:
   1405 	case GL_GREATER:
   1406 	case GL_GEQUAL:
   1407 	case GL_NOTEQUAL:
   1408 		break;
   1409 	default:
   1410 		return error(GL_INVALID_ENUM);
   1411 	}
   1412 
   1413 	es2::Context *context = es2::getContext();
   1414 
   1415 	if(context)
   1416 	{
   1417 		context->setDepthFunc(func);
   1418 	}
   1419 }
   1420 
   1421 void DepthMask(GLboolean flag)
   1422 {
   1423 	TRACE("(GLboolean flag = %d)", flag);
   1424 
   1425 	es2::Context *context = es2::getContext();
   1426 
   1427 	if(context)
   1428 	{
   1429 		context->setDepthMask(flag != GL_FALSE);
   1430 	}
   1431 }
   1432 
   1433 void DepthRangef(GLclampf zNear, GLclampf zFar)
   1434 {
   1435 	TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
   1436 
   1437 	es2::Context *context = es2::getContext();
   1438 
   1439 	if(context)
   1440 	{
   1441 		context->setDepthRange(zNear, zFar);
   1442 	}
   1443 }
   1444 
   1445 void DetachShader(GLuint program, GLuint shader)
   1446 {
   1447 	TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
   1448 
   1449 	es2::Context *context = es2::getContext();
   1450 
   1451 	if(context)
   1452 	{
   1453 
   1454 		es2::Program *programObject = context->getProgram(program);
   1455 		es2::Shader *shaderObject = context->getShader(shader);
   1456 
   1457 		if(!programObject)
   1458 		{
   1459 			es2::Shader *shaderByProgramHandle;
   1460 			shaderByProgramHandle = context->getShader(program);
   1461 			if(!shaderByProgramHandle)
   1462 			{
   1463 				return error(GL_INVALID_VALUE);
   1464 			}
   1465 			else
   1466 			{
   1467 				return error(GL_INVALID_OPERATION);
   1468 			}
   1469 		}
   1470 
   1471 		if(!shaderObject)
   1472 		{
   1473 			es2::Program *programByShaderHandle = context->getProgram(shader);
   1474 			if(!programByShaderHandle)
   1475 			{
   1476 				return error(GL_INVALID_VALUE);
   1477 			}
   1478 			else
   1479 			{
   1480 				return error(GL_INVALID_OPERATION);
   1481 			}
   1482 		}
   1483 
   1484 		if(!programObject->detachShader(shaderObject))
   1485 		{
   1486 			return error(GL_INVALID_OPERATION);
   1487 		}
   1488 	}
   1489 }
   1490 
   1491 void Disable(GLenum cap)
   1492 {
   1493 	TRACE("(GLenum cap = 0x%X)", cap);
   1494 
   1495 	es2::Context *context = es2::getContext();
   1496 
   1497 	if(context)
   1498 	{
   1499 		switch(cap)
   1500 		{
   1501 		case GL_CULL_FACE:                     context->setCullFaceEnabled(false);                   break;
   1502 		case GL_POLYGON_OFFSET_FILL:           context->setPolygonOffsetFillEnabled(false);          break;
   1503 		case GL_SAMPLE_ALPHA_TO_COVERAGE:      context->setSampleAlphaToCoverageEnabled(false);      break;
   1504 		case GL_SAMPLE_COVERAGE:               context->setSampleCoverageEnabled(false);             break;
   1505 		case GL_SCISSOR_TEST:                  context->setScissorTestEnabled(false);                break;
   1506 		case GL_STENCIL_TEST:                  context->setStencilTestEnabled(false);                break;
   1507 		case GL_DEPTH_TEST:                    context->setDepthTestEnabled(false);                  break;
   1508 		case GL_BLEND:                         context->setBlendEnabled(false);                      break;
   1509 		case GL_DITHER:                        context->setDitherEnabled(false);                     break;
   1510 		case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
   1511 		case GL_RASTERIZER_DISCARD:            context->setRasterizerDiscardEnabled(false);          break;
   1512 		default:
   1513 			return error(GL_INVALID_ENUM);
   1514 		}
   1515 	}
   1516 }
   1517 
   1518 void DisableVertexAttribArray(GLuint index)
   1519 {
   1520 	TRACE("(GLuint index = %d)", index);
   1521 
   1522 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   1523 	{
   1524 		return error(GL_INVALID_VALUE);
   1525 	}
   1526 
   1527 	es2::Context *context = es2::getContext();
   1528 
   1529 	if(context)
   1530 	{
   1531 		context->setVertexAttribArrayEnabled(index, false);
   1532 	}
   1533 }
   1534 
   1535 void DrawArrays(GLenum mode, GLint first, GLsizei count)
   1536 {
   1537 	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
   1538 
   1539 	switch(mode)
   1540 	{
   1541 	case GL_POINTS:
   1542 	case GL_LINES:
   1543 	case GL_LINE_LOOP:
   1544 	case GL_LINE_STRIP:
   1545 	case GL_TRIANGLES:
   1546 	case GL_TRIANGLE_FAN:
   1547 	case GL_TRIANGLE_STRIP:
   1548 		break;
   1549 	default:
   1550 		return error(GL_INVALID_ENUM);
   1551 	}
   1552 
   1553 	if(count < 0 || first < 0)
   1554 	{
   1555 		return error(GL_INVALID_VALUE);
   1556 	}
   1557 
   1558 	es2::Context *context = es2::getContext();
   1559 
   1560 	if(context)
   1561 	{
   1562 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1563 		if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
   1564 		{
   1565 			return error(GL_INVALID_OPERATION);
   1566 		}
   1567 
   1568 		context->drawArrays(mode, first, count);
   1569 	}
   1570 }
   1571 
   1572 void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
   1573 {
   1574 	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
   1575 	      mode, count, type, indices);
   1576 
   1577 	switch(mode)
   1578 	{
   1579 	case GL_POINTS:
   1580 	case GL_LINES:
   1581 	case GL_LINE_LOOP:
   1582 	case GL_LINE_STRIP:
   1583 	case GL_TRIANGLES:
   1584 	case GL_TRIANGLE_FAN:
   1585 	case GL_TRIANGLE_STRIP:
   1586 		break;
   1587 	default:
   1588 		return error(GL_INVALID_ENUM);
   1589 	}
   1590 
   1591 	if(count < 0)
   1592 	{
   1593 		return error(GL_INVALID_VALUE);
   1594 	}
   1595 
   1596 	es2::Context *context = es2::getContext();
   1597 
   1598 	if(context)
   1599 	{
   1600 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1601 		if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
   1602 		{
   1603 			return error(GL_INVALID_OPERATION);
   1604 		}
   1605 
   1606 		switch(type)
   1607 		{
   1608 		case GL_UNSIGNED_BYTE:
   1609 		case GL_UNSIGNED_SHORT:
   1610 		case GL_UNSIGNED_INT:
   1611 			break;
   1612 		default:
   1613 			return error(GL_INVALID_ENUM);
   1614 		}
   1615 
   1616 		context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
   1617 	}
   1618 }
   1619 
   1620 void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
   1621 {
   1622 	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
   1623 		mode, first, count, instanceCount);
   1624 
   1625 	switch(mode)
   1626 	{
   1627 	case GL_POINTS:
   1628 	case GL_LINES:
   1629 	case GL_LINE_LOOP:
   1630 	case GL_LINE_STRIP:
   1631 	case GL_TRIANGLES:
   1632 	case GL_TRIANGLE_FAN:
   1633 	case GL_TRIANGLE_STRIP:
   1634 		break;
   1635 	default:
   1636 		return error(GL_INVALID_ENUM);
   1637 	}
   1638 
   1639 	if(count < 0 || instanceCount < 0)
   1640 	{
   1641 		return error(GL_INVALID_VALUE);
   1642 	}
   1643 
   1644 	es2::Context *context = es2::getContext();
   1645 
   1646 	if(context)
   1647 	{
   1648 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1649 		if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
   1650 		{
   1651 			return error(GL_INVALID_OPERATION);
   1652 		}
   1653 
   1654 		context->drawArrays(mode, first, count, instanceCount);
   1655 	}
   1656 }
   1657 
   1658 void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
   1659 {
   1660 	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
   1661 		mode, count, type, indices, instanceCount);
   1662 
   1663 	switch(mode)
   1664 	{
   1665 	case GL_POINTS:
   1666 	case GL_LINES:
   1667 	case GL_LINE_LOOP:
   1668 	case GL_LINE_STRIP:
   1669 	case GL_TRIANGLES:
   1670 	case GL_TRIANGLE_FAN:
   1671 	case GL_TRIANGLE_STRIP:
   1672 		break;
   1673 	default:
   1674 		return error(GL_INVALID_ENUM);
   1675 	}
   1676 
   1677 	switch(type)
   1678 	{
   1679 	case GL_UNSIGNED_BYTE:
   1680 	case GL_UNSIGNED_SHORT:
   1681 	case GL_UNSIGNED_INT:
   1682 		break;
   1683 	default:
   1684 		return error(GL_INVALID_ENUM);
   1685 	}
   1686 
   1687 	if(count < 0 || instanceCount < 0)
   1688 	{
   1689 		return error(GL_INVALID_VALUE);
   1690 	}
   1691 
   1692 	es2::Context *context = es2::getContext();
   1693 
   1694 	if(context)
   1695 	{
   1696 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1697 		if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
   1698 		{
   1699 			return error(GL_INVALID_OPERATION);
   1700 		}
   1701 
   1702 		context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
   1703 	}
   1704 }
   1705 
   1706 void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
   1707 {
   1708 	TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
   1709 
   1710 	es2::Context *context = es2::getContext();
   1711 
   1712 	if(context)
   1713 	{
   1714 		if(index >= es2::MAX_VERTEX_ATTRIBS)
   1715 		{
   1716 			return error(GL_INVALID_VALUE);
   1717 		}
   1718 
   1719 		context->setVertexAttribDivisor(index, divisor);
   1720 	}
   1721 }
   1722 
   1723 void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
   1724 {
   1725 	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
   1726 		mode, first, count, instanceCount);
   1727 
   1728 	switch(mode)
   1729 	{
   1730 	case GL_POINTS:
   1731 	case GL_LINES:
   1732 	case GL_LINE_LOOP:
   1733 	case GL_LINE_STRIP:
   1734 	case GL_TRIANGLES:
   1735 	case GL_TRIANGLE_FAN:
   1736 	case GL_TRIANGLE_STRIP:
   1737 		break;
   1738 	default:
   1739 		return error(GL_INVALID_ENUM);
   1740 	}
   1741 
   1742 	if(count < 0 || instanceCount < 0)
   1743 	{
   1744 		return error(GL_INVALID_VALUE);
   1745 	}
   1746 
   1747 	es2::Context *context = es2::getContext();
   1748 
   1749 	if(context)
   1750 	{
   1751 		if(!context->hasZeroDivisor())
   1752 		{
   1753 			return error(GL_INVALID_OPERATION);
   1754 		}
   1755 
   1756 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1757 		if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
   1758 		{
   1759 			return error(GL_INVALID_OPERATION);
   1760 		}
   1761 
   1762 		context->drawArrays(mode, first, count, instanceCount);
   1763 	}
   1764 }
   1765 
   1766 void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
   1767 {
   1768 	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
   1769 		mode, count, type, indices, instanceCount);
   1770 
   1771 	switch(mode)
   1772 	{
   1773 	case GL_POINTS:
   1774 	case GL_LINES:
   1775 	case GL_LINE_LOOP:
   1776 	case GL_LINE_STRIP:
   1777 	case GL_TRIANGLES:
   1778 	case GL_TRIANGLE_FAN:
   1779 	case GL_TRIANGLE_STRIP:
   1780 		break;
   1781 	default:
   1782 		return error(GL_INVALID_ENUM);
   1783 	}
   1784 
   1785 	switch(type)
   1786 	{
   1787 	case GL_UNSIGNED_BYTE:
   1788 	case GL_UNSIGNED_SHORT:
   1789 	case GL_UNSIGNED_INT:
   1790 		break;
   1791 	default:
   1792 		return error(GL_INVALID_ENUM);
   1793 	}
   1794 
   1795 	if(count < 0 || instanceCount < 0)
   1796 	{
   1797 		return error(GL_INVALID_VALUE);
   1798 	}
   1799 
   1800 	es2::Context *context = es2::getContext();
   1801 
   1802 	if(context)
   1803 	{
   1804 		if(!context->hasZeroDivisor())
   1805 		{
   1806 			return error(GL_INVALID_OPERATION);
   1807 		}
   1808 
   1809 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
   1810 		if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
   1811 		{
   1812 			return error(GL_INVALID_OPERATION);
   1813 		}
   1814 
   1815 		context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
   1816 	}
   1817 }
   1818 
   1819 void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
   1820 {
   1821 	TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
   1822 
   1823 	es2::Context *context = es2::getContext();
   1824 
   1825 	if(context)
   1826 	{
   1827 		if(index >= MAX_VERTEX_ATTRIBS)
   1828 		{
   1829 			return error(GL_INVALID_VALUE);
   1830 		}
   1831 
   1832 		context->setVertexAttribDivisor(index, divisor);
   1833 	}
   1834 }
   1835 
   1836 void Enable(GLenum cap)
   1837 {
   1838 	TRACE("(GLenum cap = 0x%X)", cap);
   1839 
   1840 	es2::Context *context = es2::getContext();
   1841 
   1842 	if(context)
   1843 	{
   1844 		switch(cap)
   1845 		{
   1846 		case GL_CULL_FACE:                     context->setCullFaceEnabled(true);                   break;
   1847 		case GL_POLYGON_OFFSET_FILL:           context->setPolygonOffsetFillEnabled(true);          break;
   1848 		case GL_SAMPLE_ALPHA_TO_COVERAGE:      context->setSampleAlphaToCoverageEnabled(true);      break;
   1849 		case GL_SAMPLE_COVERAGE:               context->setSampleCoverageEnabled(true);             break;
   1850 		case GL_SCISSOR_TEST:                  context->setScissorTestEnabled(true);                break;
   1851 		case GL_STENCIL_TEST:                  context->setStencilTestEnabled(true);                break;
   1852 		case GL_DEPTH_TEST:                    context->setDepthTestEnabled(true);                  break;
   1853 		case GL_BLEND:                         context->setBlendEnabled(true);                      break;
   1854 		case GL_DITHER:                        context->setDitherEnabled(true);                     break;
   1855 		case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
   1856 		case GL_RASTERIZER_DISCARD:            context->setRasterizerDiscardEnabled(true);          break;
   1857 		default:
   1858 			return error(GL_INVALID_ENUM);
   1859 		}
   1860 	}
   1861 }
   1862 
   1863 void EnableVertexAttribArray(GLuint index)
   1864 {
   1865 	TRACE("(GLuint index = %d)", index);
   1866 
   1867 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   1868 	{
   1869 		return error(GL_INVALID_VALUE);
   1870 	}
   1871 
   1872 	es2::Context *context = es2::getContext();
   1873 
   1874 	if(context)
   1875 	{
   1876 		context->setVertexAttribArrayEnabled(index, true);
   1877 	}
   1878 }
   1879 
   1880 void EndQueryEXT(GLenum target)
   1881 {
   1882 	TRACE("GLenum target = 0x%X)", target);
   1883 
   1884 	switch(target)
   1885 	{
   1886 	case GL_ANY_SAMPLES_PASSED_EXT:
   1887 	case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
   1888 		break;
   1889 	default:
   1890 		return error(GL_INVALID_ENUM);
   1891 	}
   1892 
   1893 	es2::Context *context = es2::getContext();
   1894 
   1895 	if(context)
   1896 	{
   1897 		context->endQuery(target);
   1898 	}
   1899 }
   1900 
   1901 void FinishFenceNV(GLuint fence)
   1902 {
   1903 	TRACE("(GLuint fence = %d)", fence);
   1904 
   1905 	es2::Context *context = es2::getContext();
   1906 
   1907 	if(context)
   1908 	{
   1909 		es2::Fence *fenceObject = context->getFence(fence);
   1910 
   1911 		if(!fenceObject)
   1912 		{
   1913 			return error(GL_INVALID_OPERATION);
   1914 		}
   1915 
   1916 		fenceObject->finishFence();
   1917 	}
   1918 }
   1919 
   1920 void Finish(void)
   1921 {
   1922 	TRACE("()");
   1923 
   1924 	es2::Context *context = es2::getContext();
   1925 
   1926 	if(context)
   1927 	{
   1928 		context->finish();
   1929 	}
   1930 }
   1931 
   1932 void Flush(void)
   1933 {
   1934 	TRACE("()");
   1935 
   1936 	es2::Context *context = es2::getContext();
   1937 
   1938 	if(context)
   1939 	{
   1940 		context->flush();
   1941 	}
   1942 }
   1943 
   1944 void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
   1945 {
   1946 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
   1947 	      "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
   1948 
   1949 	if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) ||
   1950 	   (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
   1951 	{
   1952 		return error(GL_INVALID_ENUM);
   1953 	}
   1954 
   1955 	es2::Context *context = es2::getContext();
   1956 
   1957 	if(context)
   1958 	{
   1959 		es2::Framebuffer *framebuffer = nullptr;
   1960 		GLuint framebufferName = 0;
   1961 		if(target == GL_READ_FRAMEBUFFER_ANGLE)
   1962 		{
   1963 			framebuffer = context->getReadFramebuffer();
   1964 			framebufferName = context->getReadFramebufferName();
   1965 		}
   1966 		else
   1967 		{
   1968 			framebuffer = context->getDrawFramebuffer();
   1969 			framebufferName = context->getDrawFramebufferName();
   1970 		}
   1971 
   1972 		if(!framebuffer || framebufferName == 0)
   1973 		{
   1974 			return error(GL_INVALID_OPERATION);
   1975 		}
   1976 
   1977 		// [OpenGL ES 2.0.25] Section 4.4.3 page 112
   1978 		// [OpenGL ES 3.0.2] Section 4.4.2 page 201
   1979 		// 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
   1980 		// type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
   1981 		if(renderbuffer != 0)
   1982 		{
   1983 			if(!context->getRenderbuffer(renderbuffer))
   1984 			{
   1985 				return error(GL_INVALID_OPERATION);
   1986 			}
   1987 		}
   1988 
   1989 		GLint clientVersion = context->getClientVersion();
   1990 
   1991 		switch(attachment)
   1992 		{
   1993 		case GL_COLOR_ATTACHMENT0:
   1994 		case GL_COLOR_ATTACHMENT1:
   1995 		case GL_COLOR_ATTACHMENT2:
   1996 		case GL_COLOR_ATTACHMENT3:
   1997 		case GL_COLOR_ATTACHMENT4:
   1998 		case GL_COLOR_ATTACHMENT5:
   1999 		case GL_COLOR_ATTACHMENT6:
   2000 		case GL_COLOR_ATTACHMENT7:
   2001 		case GL_COLOR_ATTACHMENT8:
   2002 		case GL_COLOR_ATTACHMENT9:
   2003 		case GL_COLOR_ATTACHMENT10:
   2004 		case GL_COLOR_ATTACHMENT11:
   2005 		case GL_COLOR_ATTACHMENT12:
   2006 		case GL_COLOR_ATTACHMENT13:
   2007 		case GL_COLOR_ATTACHMENT14:
   2008 		case GL_COLOR_ATTACHMENT15:
   2009 		case GL_COLOR_ATTACHMENT16:
   2010 		case GL_COLOR_ATTACHMENT17:
   2011 		case GL_COLOR_ATTACHMENT18:
   2012 		case GL_COLOR_ATTACHMENT19:
   2013 		case GL_COLOR_ATTACHMENT20:
   2014 		case GL_COLOR_ATTACHMENT21:
   2015 		case GL_COLOR_ATTACHMENT22:
   2016 		case GL_COLOR_ATTACHMENT23:
   2017 		case GL_COLOR_ATTACHMENT24:
   2018 		case GL_COLOR_ATTACHMENT25:
   2019 		case GL_COLOR_ATTACHMENT26:
   2020 		case GL_COLOR_ATTACHMENT27:
   2021 		case GL_COLOR_ATTACHMENT28:
   2022 		case GL_COLOR_ATTACHMENT29:
   2023 		case GL_COLOR_ATTACHMENT30:
   2024 		case GL_COLOR_ATTACHMENT31:
   2025 			if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
   2026 			{
   2027 				return error(GL_INVALID_ENUM);
   2028 			}
   2029 			framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
   2030 			break;
   2031 		case GL_DEPTH_ATTACHMENT:
   2032 			framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
   2033 			break;
   2034 		case GL_STENCIL_ATTACHMENT:
   2035 			framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
   2036 			break;
   2037 		case GL_DEPTH_STENCIL_ATTACHMENT:
   2038 			if(clientVersion >= 3)
   2039 			{
   2040 				framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
   2041 				framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
   2042 				break;
   2043 			}
   2044 			else return error(GL_INVALID_ENUM);
   2045 		default:
   2046 			return error(GL_INVALID_ENUM);
   2047 		}
   2048 	}
   2049 }
   2050 
   2051 void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
   2052 {
   2053 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
   2054 	      "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
   2055 
   2056 	if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
   2057 	{
   2058 		return error(GL_INVALID_ENUM);
   2059 	}
   2060 
   2061 	es2::Context *context = es2::getContext();
   2062 
   2063 	if(context)
   2064 	{
   2065 		GLint clientVersion = context->getClientVersion();
   2066 
   2067 		if(texture == 0)
   2068 		{
   2069 			textarget = GL_NONE;
   2070 		}
   2071 		else
   2072 		{
   2073 			es2::Texture *tex = context->getTexture(texture);
   2074 
   2075 			if(!tex)
   2076 			{
   2077 				return error(GL_INVALID_OPERATION);
   2078 			}
   2079 
   2080 			switch(textarget)
   2081 			{
   2082 			case GL_TEXTURE_2D:
   2083 				if(tex->getTarget() != GL_TEXTURE_2D)
   2084 				{
   2085 					return error(GL_INVALID_OPERATION);
   2086 				}
   2087 				break;
   2088 			case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   2089 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   2090 			case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   2091 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   2092 			case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   2093 			case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   2094 				if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
   2095 				{
   2096 					return error(GL_INVALID_OPERATION);
   2097 				}
   2098 				break;
   2099 			default:
   2100 				return error(GL_INVALID_ENUM);
   2101 			}
   2102 
   2103 			if((level != 0) && (clientVersion < 3))
   2104 			{
   2105 				return error(GL_INVALID_VALUE);
   2106 			}
   2107 
   2108 			if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
   2109 			{
   2110 				return error(GL_INVALID_VALUE);
   2111 			}
   2112 
   2113 			if(tex->isCompressed(textarget, level))
   2114 			{
   2115 				return error(GL_INVALID_OPERATION);
   2116 			}
   2117 		}
   2118 
   2119 		es2::Framebuffer *framebuffer = nullptr;
   2120 		GLuint framebufferName = 0;
   2121 		if(target == GL_READ_FRAMEBUFFER_ANGLE)
   2122 		{
   2123 			framebuffer = context->getReadFramebuffer();
   2124 			framebufferName = context->getReadFramebufferName();
   2125 		}
   2126 		else
   2127 		{
   2128 			framebuffer = context->getDrawFramebuffer();
   2129 			framebufferName = context->getDrawFramebufferName();
   2130 		}
   2131 
   2132 		if(framebufferName == 0 || !framebuffer)
   2133 		{
   2134 			return error(GL_INVALID_OPERATION);
   2135 		}
   2136 
   2137 		switch(attachment)
   2138 		{
   2139 		case GL_COLOR_ATTACHMENT0:
   2140 		case GL_COLOR_ATTACHMENT1:
   2141 		case GL_COLOR_ATTACHMENT2:
   2142 		case GL_COLOR_ATTACHMENT3:
   2143 		case GL_COLOR_ATTACHMENT4:
   2144 		case GL_COLOR_ATTACHMENT5:
   2145 		case GL_COLOR_ATTACHMENT6:
   2146 		case GL_COLOR_ATTACHMENT7:
   2147 		case GL_COLOR_ATTACHMENT8:
   2148 		case GL_COLOR_ATTACHMENT9:
   2149 		case GL_COLOR_ATTACHMENT10:
   2150 		case GL_COLOR_ATTACHMENT11:
   2151 		case GL_COLOR_ATTACHMENT12:
   2152 		case GL_COLOR_ATTACHMENT13:
   2153 		case GL_COLOR_ATTACHMENT14:
   2154 		case GL_COLOR_ATTACHMENT15:
   2155 		case GL_COLOR_ATTACHMENT16:
   2156 		case GL_COLOR_ATTACHMENT17:
   2157 		case GL_COLOR_ATTACHMENT18:
   2158 		case GL_COLOR_ATTACHMENT19:
   2159 		case GL_COLOR_ATTACHMENT20:
   2160 		case GL_COLOR_ATTACHMENT21:
   2161 		case GL_COLOR_ATTACHMENT22:
   2162 		case GL_COLOR_ATTACHMENT23:
   2163 		case GL_COLOR_ATTACHMENT24:
   2164 		case GL_COLOR_ATTACHMENT25:
   2165 		case GL_COLOR_ATTACHMENT26:
   2166 		case GL_COLOR_ATTACHMENT27:
   2167 		case GL_COLOR_ATTACHMENT28:
   2168 		case GL_COLOR_ATTACHMENT29:
   2169 		case GL_COLOR_ATTACHMENT30:
   2170 		case GL_COLOR_ATTACHMENT31:
   2171 			if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
   2172 			{
   2173 				return error(GL_INVALID_ENUM);
   2174 			}
   2175 			framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
   2176 			break;
   2177 		case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture, level);   break;
   2178 		case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
   2179 		case GL_DEPTH_STENCIL_ATTACHMENT:
   2180 			if(clientVersion >= 3)
   2181 			{
   2182 				framebuffer->setDepthbuffer(textarget, texture, level);
   2183 				framebuffer->setStencilbuffer(textarget, texture, level);
   2184 				break;
   2185 			}
   2186 			else return error(GL_INVALID_ENUM);
   2187 		default:
   2188 			return error(GL_INVALID_ENUM);
   2189 		}
   2190 	}
   2191 }
   2192 
   2193 void FrontFace(GLenum mode)
   2194 {
   2195 	TRACE("(GLenum mode = 0x%X)", mode);
   2196 
   2197 	switch(mode)
   2198 	{
   2199 	case GL_CW:
   2200 	case GL_CCW:
   2201 		{
   2202 			es2::Context *context = es2::getContext();
   2203 
   2204 			if(context)
   2205 			{
   2206 				context->setFrontFace(mode);
   2207 			}
   2208 		}
   2209 		break;
   2210 	default:
   2211 		return error(GL_INVALID_ENUM);
   2212 	}
   2213 }
   2214 
   2215 void GenBuffers(GLsizei n, GLuint* buffers)
   2216 {
   2217 	TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
   2218 
   2219 	if(n < 0)
   2220 	{
   2221 		return error(GL_INVALID_VALUE);
   2222 	}
   2223 
   2224 	es2::Context *context = es2::getContext();
   2225 
   2226 	if(context)
   2227 	{
   2228 		for(int i = 0; i < n; i++)
   2229 		{
   2230 			buffers[i] = context->createBuffer();
   2231 		}
   2232 	}
   2233 }
   2234 
   2235 void GenerateMipmap(GLenum target)
   2236 {
   2237 	TRACE("(GLenum target = 0x%X)", target);
   2238 
   2239 	es2::Context *context = es2::getContext();
   2240 
   2241 	if(context)
   2242 	{
   2243 		es2::Texture *texture = nullptr;
   2244 
   2245 		GLint clientVersion = context->getClientVersion();
   2246 
   2247 		switch(target)
   2248 		{
   2249 		case GL_TEXTURE_2D:
   2250 			texture = context->getTexture2D();
   2251 			break;
   2252 		case GL_TEXTURE_CUBE_MAP:
   2253 			texture = context->getTextureCubeMap();
   2254 			break;
   2255 		case GL_TEXTURE_2D_ARRAY:
   2256 			if(clientVersion < 3)
   2257 			{
   2258 				return error(GL_INVALID_ENUM);
   2259 			}
   2260 			else
   2261 			{
   2262 				texture = context->getTexture2DArray();
   2263 			}
   2264 			break;
   2265 		case GL_TEXTURE_3D_OES:
   2266 			texture = context->getTexture3D();
   2267 			break;
   2268 		default:
   2269 			return error(GL_INVALID_ENUM);
   2270 		}
   2271 
   2272 		if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
   2273 		{
   2274 			return error(GL_INVALID_OPERATION);
   2275 		}
   2276 
   2277 		texture->generateMipmaps();
   2278 	}
   2279 }
   2280 
   2281 void GenFencesNV(GLsizei n, GLuint* fences)
   2282 {
   2283 	TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
   2284 
   2285 	if(n < 0)
   2286 	{
   2287 		return error(GL_INVALID_VALUE);
   2288 	}
   2289 
   2290 	es2::Context *context = es2::getContext();
   2291 
   2292 	if(context)
   2293 	{
   2294 		for(int i = 0; i < n; i++)
   2295 		{
   2296 			fences[i] = context->createFence();
   2297 		}
   2298 	}
   2299 }
   2300 
   2301 void GenFramebuffers(GLsizei n, GLuint* framebuffers)
   2302 {
   2303 	TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
   2304 
   2305 	if(n < 0)
   2306 	{
   2307 		return error(GL_INVALID_VALUE);
   2308 	}
   2309 
   2310 	es2::Context *context = es2::getContext();
   2311 
   2312 	if(context)
   2313 	{
   2314 		for(int i = 0; i < n; i++)
   2315 		{
   2316 			framebuffers[i] = context->createFramebuffer();
   2317 		}
   2318 	}
   2319 }
   2320 
   2321 void GenQueriesEXT(GLsizei n, GLuint* ids)
   2322 {
   2323 	TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
   2324 
   2325 	if(n < 0)
   2326 	{
   2327 		return error(GL_INVALID_VALUE);
   2328 	}
   2329 
   2330 	es2::Context *context = es2::getContext();
   2331 
   2332 	if(context)
   2333 	{
   2334 		for(int i = 0; i < n; i++)
   2335 		{
   2336 			ids[i] = context->createQuery();
   2337 		}
   2338 	}
   2339 }
   2340 
   2341 void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
   2342 {
   2343 	TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
   2344 
   2345 	if(n < 0)
   2346 	{
   2347 		return error(GL_INVALID_VALUE);
   2348 	}
   2349 
   2350 	es2::Context *context = es2::getContext();
   2351 
   2352 	if(context)
   2353 	{
   2354 		for(int i = 0; i < n; i++)
   2355 		{
   2356 			renderbuffers[i] = context->createRenderbuffer();
   2357 		}
   2358 	}
   2359 }
   2360 
   2361 void GenTextures(GLsizei n, GLuint* textures)
   2362 {
   2363 	TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
   2364 
   2365 	if(n < 0)
   2366 	{
   2367 		return error(GL_INVALID_VALUE);
   2368 	}
   2369 
   2370 	es2::Context *context = es2::getContext();
   2371 
   2372 	if(context)
   2373 	{
   2374 		for(int i = 0; i < n; i++)
   2375 		{
   2376 			textures[i] = context->createTexture();
   2377 		}
   2378 	}
   2379 }
   2380 
   2381 void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
   2382 {
   2383 	TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
   2384 	      "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
   2385 	      program, index, bufsize, length, size, type, name);
   2386 
   2387 	if(bufsize < 0)
   2388 	{
   2389 		return error(GL_INVALID_VALUE);
   2390 	}
   2391 
   2392 	es2::Context *context = es2::getContext();
   2393 
   2394 	if(context)
   2395 	{
   2396 		es2::Program *programObject = context->getProgram(program);
   2397 
   2398 		if(!programObject)
   2399 		{
   2400 			if(context->getShader(program))
   2401 			{
   2402 				return error(GL_INVALID_OPERATION);
   2403 			}
   2404 			else
   2405 			{
   2406 				return error(GL_INVALID_VALUE);
   2407 			}
   2408 		}
   2409 
   2410 		if(index >= programObject->getActiveAttributeCount())
   2411 		{
   2412 			return error(GL_INVALID_VALUE);
   2413 		}
   2414 
   2415 		programObject->getActiveAttribute(index, bufsize, length, size, type, name);
   2416 	}
   2417 }
   2418 
   2419 void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
   2420 {
   2421 	TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
   2422 	      "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
   2423 	      program, index, bufsize, length, size, type, name);
   2424 
   2425 	if(bufsize < 0)
   2426 	{
   2427 		return error(GL_INVALID_VALUE);
   2428 	}
   2429 
   2430 	es2::Context *context = es2::getContext();
   2431 
   2432 	if(context)
   2433 	{
   2434 		es2::Program *programObject = context->getProgram(program);
   2435 
   2436 		if(!programObject)
   2437 		{
   2438 			if(context->getShader(program))
   2439 			{
   2440 				return error(GL_INVALID_OPERATION);
   2441 			}
   2442 			else
   2443 			{
   2444 				return error(GL_INVALID_VALUE);
   2445 			}
   2446 		}
   2447 
   2448 		if(index >= programObject->getActiveUniformCount())
   2449 		{
   2450 			return error(GL_INVALID_VALUE);
   2451 		}
   2452 
   2453 		programObject->getActiveUniform(index, bufsize, length, size, type, name);
   2454 	}
   2455 }
   2456 
   2457 void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
   2458 {
   2459 	TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
   2460 	      program, maxcount, count, shaders);
   2461 
   2462 	if(maxcount < 0)
   2463 	{
   2464 		return error(GL_INVALID_VALUE);
   2465 	}
   2466 
   2467 	es2::Context *context = es2::getContext();
   2468 
   2469 	if(context)
   2470 	{
   2471 		es2::Program *programObject = context->getProgram(program);
   2472 
   2473 		if(!programObject)
   2474 		{
   2475 			if(context->getShader(program))
   2476 			{
   2477 				return error(GL_INVALID_OPERATION);
   2478 			}
   2479 			else
   2480 			{
   2481 				return error(GL_INVALID_VALUE);
   2482 			}
   2483 		}
   2484 
   2485 		return programObject->getAttachedShaders(maxcount, count, shaders);
   2486 	}
   2487 }
   2488 
   2489 int GetAttribLocation(GLuint program, const GLchar* name)
   2490 {
   2491 	TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
   2492 
   2493 	es2::Context *context = es2::getContext();
   2494 
   2495 	if(context)
   2496 	{
   2497 
   2498 		es2::Program *programObject = context->getProgram(program);
   2499 
   2500 		if(!programObject)
   2501 		{
   2502 			if(context->getShader(program))
   2503 			{
   2504 				return error(GL_INVALID_OPERATION, -1);
   2505 			}
   2506 			else
   2507 			{
   2508 				return error(GL_INVALID_VALUE, -1);
   2509 			}
   2510 		}
   2511 
   2512 		if(!programObject->isLinked())
   2513 		{
   2514 			return error(GL_INVALID_OPERATION, -1);
   2515 		}
   2516 
   2517 		return programObject->getAttributeLocation(name);
   2518 	}
   2519 
   2520 	return -1;
   2521 }
   2522 
   2523 void GetBooleanv(GLenum pname, GLboolean* params)
   2524 {
   2525 	TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)",  pname, params);
   2526 
   2527 	es2::Context *context = es2::getContext();
   2528 
   2529 	if(context)
   2530 	{
   2531 		if(!(context->getBooleanv(pname, params)))
   2532 		{
   2533 			GLenum nativeType;
   2534 			unsigned int numParams = 0;
   2535 			if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
   2536 				return error(GL_INVALID_ENUM);
   2537 
   2538 			if(numParams == 0)
   2539 				return; // it is known that the pname is valid, but there are no parameters to return
   2540 
   2541 			if(nativeType == GL_FLOAT)
   2542 			{
   2543 				GLfloat *floatParams = nullptr;
   2544 				floatParams = new GLfloat[numParams];
   2545 
   2546 				context->getFloatv(pname, floatParams);
   2547 
   2548 				for(unsigned int i = 0; i < numParams; ++i)
   2549 				{
   2550 					if(floatParams[i] == 0.0f)
   2551 						params[i] = GL_FALSE;
   2552 					else
   2553 						params[i] = GL_TRUE;
   2554 				}
   2555 
   2556 				delete [] floatParams;
   2557 			}
   2558 			else if(nativeType == GL_INT)
   2559 			{
   2560 				GLint *intParams = nullptr;
   2561 				intParams = new GLint[numParams];
   2562 
   2563 				context->getIntegerv(pname, intParams);
   2564 
   2565 				for(unsigned int i = 0; i < numParams; ++i)
   2566 				{
   2567 					if(intParams[i] == 0)
   2568 						params[i] = GL_FALSE;
   2569 					else
   2570 						params[i] = GL_TRUE;
   2571 				}
   2572 
   2573 				delete [] intParams;
   2574 			}
   2575 		}
   2576 	}
   2577 }
   2578 
   2579 void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
   2580 {
   2581 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
   2582 
   2583 	es2::Context *context = es2::getContext();
   2584 
   2585 	if(context)
   2586 	{
   2587 		es2::Buffer *buffer;
   2588 		if(!context->getBuffer(target, &buffer))
   2589 		{
   2590 			return error(GL_INVALID_ENUM);
   2591 		}
   2592 
   2593 		if(!buffer)
   2594 		{
   2595 			// A null buffer means that "0" is bound to the requested buffer target
   2596 			return error(GL_INVALID_OPERATION);
   2597 		}
   2598 
   2599 		GLint clientVersion = context->getClientVersion();
   2600 
   2601 		switch(pname)
   2602 		{
   2603 		case GL_BUFFER_USAGE:
   2604 			*params = buffer->usage();
   2605 			break;
   2606 		case GL_BUFFER_SIZE:
   2607 			*params = (GLint)buffer->size();
   2608 			break;
   2609 		case GL_BUFFER_ACCESS_FLAGS:
   2610 			if(clientVersion >= 3)
   2611 			{
   2612 				*params = buffer->access();
   2613 				break;
   2614 			}
   2615 			else return error(GL_INVALID_ENUM);
   2616 		case GL_BUFFER_MAPPED:
   2617 			if(clientVersion >= 3)
   2618 			{
   2619 				*params = buffer->isMapped();
   2620 				break;
   2621 			}
   2622 			else return error(GL_INVALID_ENUM);
   2623 		case GL_BUFFER_MAP_LENGTH:
   2624 			if(clientVersion >= 3)
   2625 			{
   2626 				*params = (GLint)buffer->length();
   2627 				break;
   2628 			}
   2629 			else return error(GL_INVALID_ENUM);
   2630 		case GL_BUFFER_MAP_OFFSET:
   2631 			if(clientVersion >= 3)
   2632 			{
   2633 				*params = (GLint)buffer->offset();
   2634 				break;
   2635 			}
   2636 			else return error(GL_INVALID_ENUM);
   2637 		default:
   2638 			return error(GL_INVALID_ENUM);
   2639 		}
   2640 	}
   2641 }
   2642 
   2643 GLenum GetError(void)
   2644 {
   2645 	TRACE("()");
   2646 
   2647 	es2::Context *context = es2::getContext();
   2648 
   2649 	if(context)
   2650 	{
   2651 		return context->getError();
   2652 	}
   2653 
   2654 	return GL_NO_ERROR;
   2655 }
   2656 
   2657 void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
   2658 {
   2659 	TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
   2660 
   2661 	es2::Context *context = es2::getContext();
   2662 
   2663 	if(context)
   2664 	{
   2665 		es2::Fence *fenceObject = context->getFence(fence);
   2666 
   2667 		if(!fenceObject)
   2668 		{
   2669 			return error(GL_INVALID_OPERATION);
   2670 		}
   2671 
   2672 		fenceObject->getFenceiv(pname, params);
   2673 	}
   2674 }
   2675 
   2676 void GetFloatv(GLenum pname, GLfloat* params)
   2677 {
   2678 	TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
   2679 
   2680 	es2::Context *context = es2::getContext();
   2681 
   2682 	if(context)
   2683 	{
   2684 		if(!(context->getFloatv(pname, params)))
   2685 		{
   2686 			GLenum nativeType;
   2687 			unsigned int numParams = 0;
   2688 			if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
   2689 				return error(GL_INVALID_ENUM);
   2690 
   2691 			if(numParams == 0)
   2692 				return; // it is known that the pname is valid, but that there are no parameters to return.
   2693 
   2694 			if(nativeType == GL_BOOL)
   2695 			{
   2696 				GLboolean *boolParams = nullptr;
   2697 				boolParams = new GLboolean[numParams];
   2698 
   2699 				context->getBooleanv(pname, boolParams);
   2700 
   2701 				for(unsigned int i = 0; i < numParams; ++i)
   2702 				{
   2703 					if(boolParams[i] == GL_FALSE)
   2704 						params[i] = 0.0f;
   2705 					else
   2706 						params[i] = 1.0f;
   2707 				}
   2708 
   2709 				delete [] boolParams;
   2710 			}
   2711 			else if(nativeType == GL_INT)
   2712 			{
   2713 				GLint *intParams = nullptr;
   2714 				intParams = new GLint[numParams];
   2715 
   2716 				context->getIntegerv(pname, intParams);
   2717 
   2718 				for(unsigned int i = 0; i < numParams; ++i)
   2719 				{
   2720 					params[i] = (GLfloat)intParams[i];
   2721 				}
   2722 
   2723 				delete [] intParams;
   2724 			}
   2725 		}
   2726 	}
   2727 }
   2728 
   2729 void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
   2730 {
   2731 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
   2732 	      target, attachment, pname, params);
   2733 
   2734 	es2::Context *context = es2::getContext();
   2735 
   2736 	if(context)
   2737 	{
   2738 		if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
   2739 		{
   2740 			return error(GL_INVALID_ENUM);
   2741 		}
   2742 
   2743 		GLint clientVersion = context->getClientVersion();
   2744 
   2745 		es2::Framebuffer *framebuffer = nullptr;
   2746 		if(target == GL_READ_FRAMEBUFFER)
   2747 		{
   2748 			if(context->getReadFramebufferName() == 0)
   2749 			{
   2750 				if(clientVersion < 3)
   2751 				{
   2752 					return error(GL_INVALID_OPERATION);
   2753 				}
   2754 				else
   2755 				{
   2756 					switch(attachment)
   2757 					{
   2758 					case GL_BACK:
   2759 					case GL_DEPTH:
   2760 					case GL_STENCIL:
   2761 						break;
   2762 					default:
   2763 						return error(GL_INVALID_ENUM);
   2764 					}
   2765 				}
   2766 			}
   2767 
   2768 			framebuffer = context->getReadFramebuffer();
   2769 		}
   2770 		else
   2771 		{
   2772 			if(context->getDrawFramebufferName() == 0)
   2773 			{
   2774 				if(clientVersion < 3)
   2775 				{
   2776 					return error(GL_INVALID_OPERATION);
   2777 				}
   2778 				else
   2779 				{
   2780 					switch(attachment)
   2781 					{
   2782 					case GL_BACK:
   2783 					case GL_DEPTH:
   2784 					case GL_STENCIL:
   2785 						break;
   2786 					default:
   2787 						return error(GL_INVALID_ENUM);
   2788 					}
   2789 				}
   2790 			}
   2791 
   2792 			framebuffer = context->getDrawFramebuffer();
   2793 		}
   2794 
   2795 		GLenum attachmentType;
   2796 		GLuint attachmentHandle;
   2797 		GLint attachmentLayer;
   2798 		Renderbuffer* renderbuffer = nullptr;
   2799 		switch(attachment)
   2800 		{
   2801 		case GL_BACK:
   2802 			if(clientVersion >= 3)
   2803 			{
   2804 				attachmentType = framebuffer->getColorbufferType(0);
   2805 				attachmentHandle = framebuffer->getColorbufferName(0);
   2806 				attachmentLayer = framebuffer->getColorbufferLayer(0);
   2807 				renderbuffer = framebuffer->getColorbuffer(0);
   2808 			}
   2809 			else return error(GL_INVALID_ENUM);
   2810 			break;
   2811 		case GL_COLOR_ATTACHMENT0:
   2812 		case GL_COLOR_ATTACHMENT1:
   2813 		case GL_COLOR_ATTACHMENT2:
   2814 		case GL_COLOR_ATTACHMENT3:
   2815 		case GL_COLOR_ATTACHMENT4:
   2816 		case GL_COLOR_ATTACHMENT5:
   2817 		case GL_COLOR_ATTACHMENT6:
   2818 		case GL_COLOR_ATTACHMENT7:
   2819 		case GL_COLOR_ATTACHMENT8:
   2820 		case GL_COLOR_ATTACHMENT9:
   2821 		case GL_COLOR_ATTACHMENT10:
   2822 		case GL_COLOR_ATTACHMENT11:
   2823 		case GL_COLOR_ATTACHMENT12:
   2824 		case GL_COLOR_ATTACHMENT13:
   2825 		case GL_COLOR_ATTACHMENT14:
   2826 		case GL_COLOR_ATTACHMENT15:
   2827 		case GL_COLOR_ATTACHMENT16:
   2828 		case GL_COLOR_ATTACHMENT17:
   2829 		case GL_COLOR_ATTACHMENT18:
   2830 		case GL_COLOR_ATTACHMENT19:
   2831 		case GL_COLOR_ATTACHMENT20:
   2832 		case GL_COLOR_ATTACHMENT21:
   2833 		case GL_COLOR_ATTACHMENT22:
   2834 		case GL_COLOR_ATTACHMENT23:
   2835 		case GL_COLOR_ATTACHMENT24:
   2836 		case GL_COLOR_ATTACHMENT25:
   2837 		case GL_COLOR_ATTACHMENT26:
   2838 		case GL_COLOR_ATTACHMENT27:
   2839 		case GL_COLOR_ATTACHMENT28:
   2840 		case GL_COLOR_ATTACHMENT29:
   2841 		case GL_COLOR_ATTACHMENT30:
   2842 		case GL_COLOR_ATTACHMENT31:
   2843 			if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
   2844 			{
   2845 				return error(GL_INVALID_ENUM);
   2846 			}
   2847 			attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
   2848 			attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
   2849 			attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
   2850 			renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
   2851 			break;
   2852 		case GL_DEPTH:
   2853 			if(clientVersion < 3)
   2854 			{
   2855 				return error(GL_INVALID_ENUM);
   2856 			}
   2857 			// fall through
   2858 		case GL_DEPTH_ATTACHMENT:
   2859 			attachmentType = framebuffer->getDepthbufferType();
   2860 			attachmentHandle = framebuffer->getDepthbufferName();
   2861 			attachmentLayer = framebuffer->getDepthbufferLayer();
   2862 			renderbuffer = framebuffer->getDepthbuffer();
   2863 			break;
   2864 		case GL_STENCIL:
   2865 			if(clientVersion < 3)
   2866 			{
   2867 				return error(GL_INVALID_ENUM);
   2868 			}
   2869 			// fall through
   2870 		case GL_STENCIL_ATTACHMENT:
   2871 			attachmentType = framebuffer->getStencilbufferType();
   2872 			attachmentHandle = framebuffer->getStencilbufferName();
   2873 			attachmentLayer = framebuffer->getStencilbufferLayer();
   2874 			renderbuffer = framebuffer->getStencilbuffer();
   2875 			break;
   2876 		case GL_DEPTH_STENCIL_ATTACHMENT:
   2877 			if(clientVersion >= 3)
   2878 			{
   2879 				attachmentType = framebuffer->getDepthbufferType();
   2880 				attachmentHandle = framebuffer->getDepthbufferName();
   2881 				attachmentLayer = framebuffer->getDepthbufferLayer();
   2882 				if(attachmentHandle != framebuffer->getStencilbufferName())
   2883 				{
   2884 					// Different attachments to DEPTH and STENCIL, query fails
   2885 					return error(GL_INVALID_OPERATION);
   2886 				}
   2887 				renderbuffer = framebuffer->getDepthbuffer();
   2888 			}
   2889 			else return error(GL_INVALID_ENUM);
   2890 			break;
   2891 		default:
   2892 			return error(GL_INVALID_ENUM);
   2893 		}
   2894 
   2895 		GLenum attachmentObjectType = GL_NONE;   // Type category
   2896 		if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
   2897 		{
   2898 			attachmentObjectType = attachmentType;
   2899 		}
   2900 		else if(es2::IsTextureTarget(attachmentType))
   2901 		{
   2902 			attachmentObjectType = GL_TEXTURE;
   2903 		}
   2904 		else UNREACHABLE(attachmentType);
   2905 
   2906 		if(attachmentObjectType != GL_NONE)
   2907 		{
   2908 			switch(pname)
   2909 			{
   2910 			case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
   2911 				*params = attachmentObjectType;
   2912 				break;
   2913 			case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
   2914 				if(Framebuffer::IsRenderbuffer(attachmentObjectType) || attachmentObjectType == GL_TEXTURE)
   2915 				{
   2916 					*params = attachmentHandle;
   2917 				}
   2918 				else
   2919 				{
   2920 					return error(GL_INVALID_ENUM);
   2921 				}
   2922 				break;
   2923 			case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
   2924 				if(attachmentObjectType == GL_TEXTURE)
   2925 				{
   2926 					*params = clientVersion < 3 ? 0 : renderbuffer->getLevel(); // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
   2927 				}
   2928 				else
   2929 				{
   2930 					return error(GL_INVALID_ENUM);
   2931 				}
   2932 				break;
   2933 			case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
   2934 				if(attachmentObjectType == GL_TEXTURE)
   2935 				{
   2936 					if(es2::IsCubemapTextureTarget(attachmentType))
   2937 					{
   2938 						*params = attachmentType;
   2939 					}
   2940 					else
   2941 					{
   2942 						*params = 0;
   2943 					}
   2944 				}
   2945 				else
   2946 				{
   2947 					return error(GL_INVALID_ENUM);
   2948 				}
   2949 				break;
   2950 			case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
   2951 				if(clientVersion >= 3)
   2952 				{
   2953 					*params = attachmentLayer;
   2954 				}
   2955 				else return error(GL_INVALID_ENUM);
   2956 				break;
   2957 			case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
   2958 				if(clientVersion >= 3)
   2959 				{
   2960 					*params = renderbuffer->getRedSize();
   2961 				}
   2962 				else return error(GL_INVALID_ENUM);
   2963 				break;
   2964 			case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
   2965 				if(clientVersion >= 3)
   2966 				{
   2967 					*params = renderbuffer->getGreenSize();
   2968 				}
   2969 				else return error(GL_INVALID_ENUM);
   2970 				break;
   2971 			case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
   2972 				if(clientVersion >= 3)
   2973 				{
   2974 					*params = renderbuffer->getBlueSize();
   2975 				}
   2976 				else return error(GL_INVALID_ENUM);
   2977 				break;
   2978 			case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
   2979 				if(clientVersion >= 3)
   2980 				{
   2981 					*params = renderbuffer->getAlphaSize();
   2982 				}
   2983 				else return error(GL_INVALID_ENUM);
   2984 				break;
   2985 			case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
   2986 				if(clientVersion >= 3)
   2987 				{
   2988 					*params = renderbuffer->getDepthSize();
   2989 				}
   2990 				else return error(GL_INVALID_ENUM);
   2991 				break;
   2992 			case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
   2993 				if(clientVersion >= 3)
   2994 				{
   2995 					*params = renderbuffer->getStencilSize();
   2996 				}
   2997 				else return error(GL_INVALID_ENUM);
   2998 				break;
   2999 			case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
   3000 		//	case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT:   // GL_EXT_color_buffer_half_float
   3001 				if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
   3002 				{
   3003 					return error(GL_INVALID_OPERATION);
   3004 				}
   3005 
   3006 				*params = sw2es::GetComponentType(renderbuffer->getInternalFormat(), attachment);
   3007 				break;
   3008 			case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
   3009 				if(clientVersion >= 3)
   3010 				{
   3011 					*params = GL_LINEAR; // FIXME: GL_SRGB will also be possible, when sRGB is added
   3012 				}
   3013 				else return error(GL_INVALID_ENUM);
   3014 				break;
   3015 			default:
   3016 				return error(GL_INVALID_ENUM);
   3017 			}
   3018 		}
   3019 		else
   3020 		{
   3021 			// ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
   3022 			// is NONE, then querying any other pname will generate INVALID_ENUM.
   3023 
   3024 			// ES 3.0.2 spec pg 235 states that if the attachment type is none,
   3025 			// GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
   3026 			// INVALID_OPERATION for all other pnames
   3027 
   3028 			switch(pname)
   3029 			{
   3030 			case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
   3031 				*params = GL_NONE;
   3032 				break;
   3033 
   3034 			case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
   3035 				if(clientVersion < 3)
   3036 				{
   3037 					return error(GL_INVALID_ENUM);
   3038 				}
   3039 				*params = 0;
   3040 				break;
   3041 
   3042 			default:
   3043 				if(clientVersion < 3)
   3044 				{
   3045 					return error(GL_INVALID_ENUM);
   3046 				}
   3047 				else
   3048 				{
   3049 					return error(GL_INVALID_OPERATION);
   3050 				}
   3051 			}
   3052 		}
   3053 	}
   3054 }
   3055 
   3056 GLenum GetGraphicsResetStatusEXT(void)
   3057 {
   3058 	TRACE("()");
   3059 
   3060 	return GL_NO_ERROR;
   3061 }
   3062 
   3063 void GetIntegerv(GLenum pname, GLint* params)
   3064 {
   3065 	TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
   3066 
   3067 	es2::Context *context = es2::getContext();
   3068 
   3069 	if(!context)
   3070 	{
   3071 		// Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
   3072 		#ifdef __ANDROID__
   3073 			ALOGI("expected_badness glGetIntegerv() called without current context.");
   3074 		#else
   3075 			ERR("glGetIntegerv() called without current context.");
   3076 		#endif
   3077 
   3078 		// This is not spec compliant! When there is no current GL context, functions should
   3079 		// have no side effects. Google Maps queries these values before creating a context,
   3080 		// so we need this as a bug-compatible workaround.
   3081 		switch(pname)
   3082 		{
   3083 		case GL_MAX_TEXTURE_SIZE:                 *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE;  return;
   3084 		case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS;   return;
   3085 		case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
   3086 		case GL_STENCIL_BITS:                     *params = 8;                                     return;
   3087 		case GL_ALIASED_LINE_WIDTH_RANGE:
   3088 			params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
   3089 			params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
   3090 			return;
   3091 		}
   3092 	}
   3093 
   3094 	if(context)
   3095 	{
   3096 		if(!(context->getIntegerv(pname, params)))
   3097 		{
   3098 			GLenum nativeType;
   3099 			unsigned int numParams = 0;
   3100 			if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
   3101 				return error(GL_INVALID_ENUM);
   3102 
   3103 			if(numParams == 0)
   3104 				return; // it is known that pname is valid, but there are no parameters to return
   3105 
   3106 			if(nativeType == GL_BOOL)
   3107 			{
   3108 				GLboolean *boolParams = nullptr;
   3109 				boolParams = new GLboolean[numParams];
   3110 
   3111 				context->getBooleanv(pname, boolParams);
   3112 
   3113 				for(unsigned int i = 0; i < numParams; ++i)
   3114 				{
   3115 					params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
   3116 				}
   3117 
   3118 				delete [] boolParams;
   3119 			}
   3120 			else if(nativeType == GL_FLOAT)
   3121 			{
   3122 				GLfloat *floatParams = nullptr;
   3123 				floatParams = new GLfloat[numParams];
   3124 
   3125 				context->getFloatv(pname, floatParams);
   3126 
   3127 				for(unsigned int i = 0; i < numParams; ++i)
   3128 				{
   3129 					if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
   3130 					{
   3131 						params[i] = convert_float_int(floatParams[i]);
   3132 					}
   3133 					else
   3134 					{
   3135 						params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
   3136 					}
   3137 				}
   3138 
   3139 				delete [] floatParams;
   3140 			}
   3141 		}
   3142 	}
   3143 }
   3144 
   3145 void GetProgramiv(GLuint program, GLenum pname, GLint* params)
   3146 {
   3147 	TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
   3148 
   3149 	es2::Context *context = es2::getContext();
   3150 
   3151 	if(context)
   3152 	{
   3153 		es2::Program *programObject = context->getProgram(program);
   3154 
   3155 		if(!programObject)
   3156 		{
   3157 			if(context->getShader(program))
   3158 			{
   3159 				return error(GL_INVALID_OPERATION);
   3160 			}
   3161 			else
   3162 			{
   3163 				return error(GL_INVALID_VALUE);
   3164 			}
   3165 		}
   3166 
   3167 		GLint clientVersion = egl::getClientVersion();
   3168 
   3169 		switch(pname)
   3170 		{
   3171 		case GL_DELETE_STATUS:
   3172 			*params = programObject->isFlaggedForDeletion();
   3173 			return;
   3174 		case GL_LINK_STATUS:
   3175 			*params = programObject->isLinked();
   3176 			return;
   3177 		case GL_VALIDATE_STATUS:
   3178 			*params = programObject->isValidated();
   3179 			return;
   3180 		case GL_INFO_LOG_LENGTH:
   3181 			*params = (GLint)programObject->getInfoLogLength();
   3182 			return;
   3183 		case GL_ATTACHED_SHADERS:
   3184 			*params = programObject->getAttachedShadersCount();
   3185 			return;
   3186 		case GL_ACTIVE_ATTRIBUTES:
   3187 			*params = (GLint)programObject->getActiveAttributeCount();
   3188 			return;
   3189 		case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
   3190 			*params = programObject->getActiveAttributeMaxLength();
   3191 			return;
   3192 		case GL_ACTIVE_UNIFORMS:
   3193 			*params = (GLint)programObject->getActiveUniformCount();
   3194 			return;
   3195 		case GL_ACTIVE_UNIFORM_MAX_LENGTH:
   3196 			*params = programObject->getActiveUniformMaxLength();
   3197 			return;
   3198 		case GL_ACTIVE_UNIFORM_BLOCKS:
   3199 			if(clientVersion >= 3)
   3200 			{
   3201 				*params = (GLint)programObject->getActiveUniformBlockCount();
   3202 				return;
   3203 			}
   3204 			else return error(GL_INVALID_ENUM);
   3205 		case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
   3206 			if(clientVersion >= 3)
   3207 			{
   3208 				*params = programObject->getActiveUniformBlockMaxLength();
   3209 				return;
   3210 			}
   3211 			else return error(GL_INVALID_ENUM);
   3212 		case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
   3213 			if(clientVersion >= 3)
   3214 			{
   3215 				*params = programObject->getTransformFeedbackBufferMode();
   3216 				return;
   3217 			}
   3218 			else return error(GL_INVALID_ENUM);
   3219 		case GL_TRANSFORM_FEEDBACK_VARYINGS:
   3220 			if(clientVersion >= 3)
   3221 			{
   3222 				*params = programObject->getTransformFeedbackVaryingCount();
   3223 				return;
   3224 			}
   3225 			else return error(GL_INVALID_ENUM);
   3226 		case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
   3227 			if(clientVersion >= 3)
   3228 			{
   3229 				*params = programObject->getTransformFeedbackVaryingMaxLength();
   3230 				return;
   3231 			}
   3232 			else return error(GL_INVALID_ENUM);
   3233 		case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
   3234 			if(clientVersion >= 3)
   3235 			{
   3236 				*params = programObject->getBinaryRetrievableHint();
   3237 				return;
   3238 			}
   3239 			else return error(GL_INVALID_ENUM);
   3240 		case GL_PROGRAM_BINARY_LENGTH:
   3241 			if(clientVersion >= 3)
   3242 			{
   3243 				*params = programObject->getBinaryLength();
   3244 				return;
   3245 			}
   3246 			else return error(GL_INVALID_ENUM);
   3247 		default:
   3248 			return error(GL_INVALID_ENUM);
   3249 		}
   3250 	}
   3251 }
   3252 
   3253 void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
   3254 {
   3255 	TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
   3256 	      program, bufsize, length, infolog);
   3257 
   3258 	if(bufsize < 0)
   3259 	{
   3260 		return error(GL_INVALID_VALUE);
   3261 	}
   3262 
   3263 	es2::Context *context = es2::getContext();
   3264 
   3265 	if(context)
   3266 	{
   3267 		es2::Program *programObject = context->getProgram(program);
   3268 
   3269 		if(!programObject)
   3270 		{
   3271 			if(context->getShader(program))
   3272 			{
   3273 				return error(GL_INVALID_OPERATION);
   3274 			}
   3275 			else
   3276 			{
   3277 				return error(GL_INVALID_VALUE);
   3278 			}
   3279 		}
   3280 
   3281 		programObject->getInfoLog(bufsize, length, infolog);
   3282 	}
   3283 }
   3284 
   3285 void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
   3286 {
   3287 	TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
   3288 
   3289 	switch(pname)
   3290 	{
   3291 	case GL_CURRENT_QUERY_EXT:
   3292 		break;
   3293 	default:
   3294 		return error(GL_INVALID_ENUM);
   3295 	}
   3296 
   3297 	es2::Context *context = es2::getContext();
   3298 
   3299 	if(context)
   3300 	{
   3301 		params[0] = context->getActiveQuery(target);
   3302 	}
   3303 }
   3304 
   3305 void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
   3306 {
   3307 	TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
   3308 
   3309 	switch(pname)
   3310 	{
   3311 	case GL_QUERY_RESULT_EXT:
   3312 	case GL_QUERY_RESULT_AVAILABLE_EXT:
   3313 		break;
   3314 	default:
   3315 		return error(GL_INVALID_ENUM);
   3316 	}
   3317 
   3318 	es2::Context *context = es2::getContext();
   3319 
   3320 	if(context)
   3321 	{
   3322 		es2::Query *queryObject = context->getQuery(name);
   3323 
   3324 		if(!queryObject)
   3325 		{
   3326 			return error(GL_INVALID_OPERATION);
   3327 		}
   3328 
   3329 		if(context->getActiveQuery(queryObject->getType()) == name)
   3330 		{
   3331 			return error(GL_INVALID_OPERATION);
   3332 		}
   3333 
   3334 		switch(pname)
   3335 		{
   3336 		case GL_QUERY_RESULT_EXT:
   3337 			params[0] = queryObject->getResult();
   3338 			break;
   3339 		case GL_QUERY_RESULT_AVAILABLE_EXT:
   3340 			params[0] = queryObject->isResultAvailable();
   3341 			break;
   3342 		default:
   3343 			ASSERT(false);
   3344 		}
   3345 	}
   3346 }
   3347 
   3348 void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
   3349 {
   3350 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
   3351 
   3352 	es2::Context *context = es2::getContext();
   3353 
   3354 	if(context)
   3355 	{
   3356 		if(target != GL_RENDERBUFFER)
   3357 		{
   3358 			return error(GL_INVALID_ENUM);
   3359 		}
   3360 
   3361 		if(context->getRenderbufferName() == 0)
   3362 		{
   3363 			return error(GL_INVALID_OPERATION);
   3364 		}
   3365 
   3366 		es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
   3367 
   3368 		switch(pname)
   3369 		{
   3370 		case GL_RENDERBUFFER_WIDTH:           *params = renderbuffer->getWidth();       break;
   3371 		case GL_RENDERBUFFER_HEIGHT:          *params = renderbuffer->getHeight();      break;
   3372 		case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat();      break;
   3373 		case GL_RENDERBUFFER_RED_SIZE:        *params = renderbuffer->getRedSize();     break;
   3374 		case GL_RENDERBUFFER_GREEN_SIZE:      *params = renderbuffer->getGreenSize();   break;
   3375 		case GL_RENDERBUFFER_BLUE_SIZE:       *params = renderbuffer->getBlueSize();    break;
   3376 		case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();   break;
   3377 		case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();   break;
   3378 		case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize(); break;
   3379 		case GL_RENDERBUFFER_SAMPLES_ANGLE:   *params = renderbuffer->getSamples();     break;
   3380 		default:
   3381 			return error(GL_INVALID_ENUM);
   3382 		}
   3383 	}
   3384 }
   3385 
   3386 void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
   3387 {
   3388 	TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
   3389 
   3390 	es2::Context *context = es2::getContext();
   3391 
   3392 	if(context)
   3393 	{
   3394 		es2::Shader *shaderObject = context->getShader(shader);
   3395 
   3396 		if(!shaderObject)
   3397 		{
   3398 			if(context->getProgram(shader))
   3399 			{
   3400 				return error(GL_INVALID_OPERATION);
   3401 			}
   3402 			else
   3403 			{
   3404 				return error(GL_INVALID_VALUE);
   3405 			}
   3406 		}
   3407 
   3408 		switch(pname)
   3409 		{
   3410 		case GL_SHADER_TYPE:
   3411 			*params = shaderObject->getType();
   3412 			return;
   3413 		case GL_DELETE_STATUS:
   3414 			*params = shaderObject->isFlaggedForDeletion();
   3415 			return;
   3416 		case GL_COMPILE_STATUS:
   3417 			*params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
   3418 			return;
   3419 		case GL_INFO_LOG_LENGTH:
   3420 			*params = (GLint)shaderObject->getInfoLogLength();
   3421 			return;
   3422 		case GL_SHADER_SOURCE_LENGTH:
   3423 			*params = (GLint)shaderObject->getSourceLength();
   3424 			return;
   3425 		default:
   3426 			return error(GL_INVALID_ENUM);
   3427 		}
   3428 	}
   3429 }
   3430 
   3431 void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
   3432 {
   3433 	TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
   3434 	      shader, bufsize, length, infolog);
   3435 
   3436 	if(bufsize < 0)
   3437 	{
   3438 		return error(GL_INVALID_VALUE);
   3439 	}
   3440 
   3441 	es2::Context *context = es2::getContext();
   3442 
   3443 	if(context)
   3444 	{
   3445 		es2::Shader *shaderObject = context->getShader(shader);
   3446 
   3447 		if(!shaderObject)
   3448 		{
   3449 			if(context->getProgram(shader))
   3450 			{
   3451 				return error(GL_INVALID_OPERATION);
   3452 			}
   3453 			else
   3454 			{
   3455 				return error(GL_INVALID_VALUE);
   3456 			}
   3457 		}
   3458 
   3459 		shaderObject->getInfoLog(bufsize, length, infolog);
   3460 	}
   3461 }
   3462 
   3463 void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
   3464 {
   3465 	TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
   3466 	      shadertype, precisiontype, range, precision);
   3467 
   3468 	switch(shadertype)
   3469 	{
   3470 	case GL_VERTEX_SHADER:
   3471 	case GL_FRAGMENT_SHADER:
   3472 		break;
   3473 	default:
   3474 		return error(GL_INVALID_ENUM);
   3475 	}
   3476 
   3477 	switch(precisiontype)
   3478 	{
   3479 	case GL_LOW_FLOAT:
   3480 	case GL_MEDIUM_FLOAT:
   3481 	case GL_HIGH_FLOAT:
   3482 		// IEEE 754 single-precision
   3483 		range[0] = 127;
   3484 		range[1] = 127;
   3485 		*precision = 23;
   3486 		break;
   3487 	case GL_LOW_INT:
   3488 	case GL_MEDIUM_INT:
   3489 	case GL_HIGH_INT:
   3490 		// Full integer precision is supported
   3491 		range[0] = 31;
   3492 		range[1] = 30;
   3493 		*precision = 0;
   3494 		break;
   3495 	default:
   3496 		return error(GL_INVALID_ENUM);
   3497 	}
   3498 }
   3499 
   3500 void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
   3501 {
   3502 	TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
   3503 	      shader, bufsize, length, source);
   3504 
   3505 	if(bufsize < 0)
   3506 	{
   3507 		return error(GL_INVALID_VALUE);
   3508 	}
   3509 
   3510 	es2::Context *context = es2::getContext();
   3511 
   3512 	if(context)
   3513 	{
   3514 		es2::Shader *shaderObject = context->getShader(shader);
   3515 
   3516 		if(!shaderObject)
   3517 		{
   3518 			if(context->getProgram(shader))
   3519 			{
   3520 				return error(GL_INVALID_OPERATION);
   3521 			}
   3522 			else
   3523 			{
   3524 				return error(GL_INVALID_VALUE);
   3525 			}
   3526 		}
   3527 
   3528 		shaderObject->getSource(bufsize, length, source);
   3529 	}
   3530 }
   3531 
   3532 const GLubyte* GetString(GLenum name)
   3533 {
   3534 	TRACE("(GLenum name = 0x%X)", name);
   3535 
   3536 	switch(name)
   3537 	{
   3538 	case GL_VENDOR:
   3539 		return (GLubyte*)"Google Inc.";
   3540 	case GL_RENDERER:
   3541 		return (GLubyte*)"Google SwiftShader";
   3542 	case GL_VERSION:
   3543 	{
   3544 		es2::Context *context = es2::getContext();
   3545 		return (context && (context->getClientVersion() >= 3)) ?
   3546 		       (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
   3547 		       (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
   3548 	}
   3549 	case GL_SHADING_LANGUAGE_VERSION:
   3550 	{
   3551 		es2::Context *context = es2::getContext();
   3552 		return (context && (context->getClientVersion() >= 3)) ?
   3553 		       (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
   3554 		       (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
   3555 	}
   3556 	case GL_EXTENSIONS:
   3557 	{
   3558 		es2::Context *context = es2::getContext();
   3559 		return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
   3560 	}
   3561 	default:
   3562 		return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
   3563 	}
   3564 }
   3565 
   3566 void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
   3567 {
   3568 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
   3569 
   3570 	es2::Context *context = es2::getContext();
   3571 
   3572 	if(context)
   3573 	{
   3574 		es2::Texture *texture;
   3575 
   3576 		GLint clientVersion = context->getClientVersion();
   3577 
   3578 		switch(target)
   3579 		{
   3580 		case GL_TEXTURE_2D:
   3581 			texture = context->getTexture2D();
   3582 			break;
   3583 		case GL_TEXTURE_CUBE_MAP:
   3584 			texture = context->getTextureCubeMap();
   3585 			break;
   3586 		case GL_TEXTURE_EXTERNAL_OES:
   3587 			texture = context->getTextureExternal();
   3588 			break;
   3589 		case GL_TEXTURE_2D_ARRAY:
   3590 			if(clientVersion < 3)
   3591 			{
   3592 				return error(GL_INVALID_ENUM);
   3593 			}
   3594 			else
   3595 			{
   3596 				texture = context->getTexture2DArray();
   3597 			}
   3598 			break;
   3599 		case GL_TEXTURE_3D_OES:
   3600 			texture = context->getTexture3D();
   3601 			break;
   3602 		default:
   3603 			return error(GL_INVALID_ENUM);
   3604 		}
   3605 
   3606 		switch(pname)
   3607 		{
   3608 		case GL_TEXTURE_MAG_FILTER:
   3609 			*params = (GLfloat)texture->getMagFilter();
   3610 			break;
   3611 		case GL_TEXTURE_MIN_FILTER:
   3612 			*params = (GLfloat)texture->getMinFilter();
   3613 			break;
   3614 		case GL_TEXTURE_WRAP_S:
   3615 			*params = (GLfloat)texture->getWrapS();
   3616 			break;
   3617 		case GL_TEXTURE_WRAP_T:
   3618 			*params = (GLfloat)texture->getWrapT();
   3619 			break;
   3620 		case GL_TEXTURE_WRAP_R_OES:
   3621 			*params = (GLfloat)texture->getWrapR();
   3622 			break;
   3623 		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   3624 			*params = texture->getMaxAnisotropy();
   3625 			break;
   3626 		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
   3627 			*params = (GLfloat)1;
   3628 			break;
   3629 		case GL_TEXTURE_BASE_LEVEL:
   3630 			if(clientVersion >= 3)
   3631 			{
   3632 				*params = (GLfloat)texture->getBaseLevel();
   3633 				break;
   3634 			}
   3635 			else return error(GL_INVALID_ENUM);
   3636 		case GL_TEXTURE_COMPARE_FUNC:
   3637 			if(clientVersion >= 3)
   3638 			{
   3639 				*params = (GLfloat)texture->getCompareFunc();
   3640 				break;
   3641 			}
   3642 			else return error(GL_INVALID_ENUM);
   3643 		case GL_TEXTURE_COMPARE_MODE:
   3644 			if(clientVersion >= 3)
   3645 			{
   3646 				*params = (GLfloat)texture->getCompareMode();
   3647 				break;
   3648 			}
   3649 			else return error(GL_INVALID_ENUM);
   3650 		case GL_TEXTURE_IMMUTABLE_FORMAT:
   3651 			if(clientVersion >= 3)
   3652 			{
   3653 				*params = (GLfloat)texture->getImmutableFormat();
   3654 				break;
   3655 			}
   3656 			else return error(GL_INVALID_ENUM);
   3657 		case GL_TEXTURE_IMMUTABLE_LEVELS:
   3658 			if(clientVersion >= 3)
   3659 			{
   3660 				*params = (GLfloat)texture->getImmutableLevels();
   3661 				break;
   3662 			}
   3663 			else return error(GL_INVALID_ENUM);
   3664 		case GL_TEXTURE_MAX_LEVEL:
   3665 			if(clientVersion >= 3)
   3666 			{
   3667 				*params = (GLfloat)texture->getMaxLevel();
   3668 				break;
   3669 			}
   3670 			else return error(GL_INVALID_ENUM);
   3671 		case GL_TEXTURE_MAX_LOD:
   3672 			if(clientVersion >= 3)
   3673 			{
   3674 				*params = texture->getMaxLOD();
   3675 				break;
   3676 			}
   3677 			else return error(GL_INVALID_ENUM);
   3678 		case GL_TEXTURE_MIN_LOD:
   3679 			if(clientVersion >= 3)
   3680 			{
   3681 				*params = texture->getMinLOD();
   3682 				break;
   3683 			}
   3684 			else return error(GL_INVALID_ENUM);
   3685 		case GL_TEXTURE_SWIZZLE_R:
   3686 			if(clientVersion >= 3)
   3687 			{
   3688 				*params = (GLfloat)texture->getSwizzleR();
   3689 				break;
   3690 			}
   3691 			else return error(GL_INVALID_ENUM);
   3692 		case GL_TEXTURE_SWIZZLE_G:
   3693 			if(clientVersion >= 3)
   3694 			{
   3695 				*params = (GLfloat)texture->getSwizzleG();
   3696 				break;
   3697 			}
   3698 			else return error(GL_INVALID_ENUM);
   3699 		case GL_TEXTURE_SWIZZLE_B:
   3700 			if(clientVersion >= 3)
   3701 			{
   3702 				*params = (GLfloat)texture->getSwizzleB();
   3703 				break;
   3704 			}
   3705 			else return error(GL_INVALID_ENUM);
   3706 		case GL_TEXTURE_SWIZZLE_A:
   3707 			if(clientVersion >= 3)
   3708 			{
   3709 				*params = (GLfloat)texture->getSwizzleA();
   3710 				break;
   3711 			}
   3712 			else return error(GL_INVALID_ENUM);
   3713 		default:
   3714 			return error(GL_INVALID_ENUM);
   3715 		}
   3716 	}
   3717 }
   3718 
   3719 void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
   3720 {
   3721 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
   3722 
   3723 	es2::Context *context = es2::getContext();
   3724 
   3725 	if(context)
   3726 	{
   3727 		es2::Texture *texture;
   3728 
   3729 		GLint clientVersion = context->getClientVersion();
   3730 
   3731 		switch(target)
   3732 		{
   3733 		case GL_TEXTURE_2D:
   3734 			texture = context->getTexture2D();
   3735 			break;
   3736 		case GL_TEXTURE_CUBE_MAP:
   3737 			texture = context->getTextureCubeMap();
   3738 			break;
   3739 		case GL_TEXTURE_EXTERNAL_OES:
   3740 			texture = context->getTextureExternal();
   3741 			break;
   3742 		case GL_TEXTURE_2D_ARRAY:
   3743 			if(clientVersion < 3)
   3744 			{
   3745 				return error(GL_INVALID_ENUM);
   3746 			}
   3747 			else
   3748 			{
   3749 				texture = context->getTexture2DArray();
   3750 			}
   3751 			break;
   3752 		case GL_TEXTURE_3D_OES:
   3753 			texture = context->getTexture3D();
   3754 			break;
   3755 		default:
   3756 			return error(GL_INVALID_ENUM);
   3757 		}
   3758 
   3759 		switch(pname)
   3760 		{
   3761 		case GL_TEXTURE_MAG_FILTER:
   3762 			*params = texture->getMagFilter();
   3763 			break;
   3764 		case GL_TEXTURE_MIN_FILTER:
   3765 			*params = texture->getMinFilter();
   3766 			break;
   3767 		case GL_TEXTURE_WRAP_S:
   3768 			*params = texture->getWrapS();
   3769 			break;
   3770 		case GL_TEXTURE_WRAP_T:
   3771 			*params = texture->getWrapT();
   3772 			break;
   3773 		case GL_TEXTURE_WRAP_R_OES:
   3774 			*params = texture->getWrapR();
   3775 			break;
   3776 		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   3777 			*params = (GLint)texture->getMaxAnisotropy();
   3778 			break;
   3779 		case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
   3780 			*params = 1;
   3781 			break;
   3782 		case GL_TEXTURE_BASE_LEVEL:
   3783 			if(clientVersion >= 3)
   3784 			{
   3785 				*params = texture->getBaseLevel();
   3786 				break;
   3787 			}
   3788 			else return error(GL_INVALID_ENUM);
   3789 		case GL_TEXTURE_COMPARE_FUNC:
   3790 			if(clientVersion >= 3)
   3791 			{
   3792 				*params = (GLint)texture->getCompareFunc();
   3793 				break;
   3794 			}
   3795 			else return error(GL_INVALID_ENUM);
   3796 		case GL_TEXTURE_COMPARE_MODE:
   3797 			if(clientVersion >= 3)
   3798 			{
   3799 				*params = (GLint)texture->getCompareMode();
   3800 				break;
   3801 			}
   3802 			else return error(GL_INVALID_ENUM);
   3803 		case GL_TEXTURE_IMMUTABLE_FORMAT:
   3804 			if(clientVersion >= 3)
   3805 			{
   3806 				*params = (GLint)texture->getImmutableFormat();
   3807 				break;
   3808 			}
   3809 			else return error(GL_INVALID_ENUM);
   3810 		case GL_TEXTURE_IMMUTABLE_LEVELS:
   3811 			if(clientVersion >= 3)
   3812 			{
   3813 				*params = (GLint)texture->getImmutableLevels();
   3814 				break;
   3815 			}
   3816 			else return error(GL_INVALID_ENUM);
   3817 		case GL_TEXTURE_MAX_LEVEL:
   3818 			if(clientVersion >= 3)
   3819 			{
   3820 				*params = texture->getMaxLevel();
   3821 				break;
   3822 			}
   3823 			else return error(GL_INVALID_ENUM);
   3824 		case GL_TEXTURE_MAX_LOD:
   3825 			if(clientVersion >= 3)
   3826 			{
   3827 				*params = (GLint)roundf(texture->getMaxLOD());
   3828 				break;
   3829 			}
   3830 			else return error(GL_INVALID_ENUM);
   3831 		case GL_TEXTURE_MIN_LOD:
   3832 			if(clientVersion >= 3)
   3833 			{
   3834 				*params = (GLint)roundf(texture->getMinLOD());
   3835 				break;
   3836 			}
   3837 			else return error(GL_INVALID_ENUM);
   3838 		case GL_TEXTURE_SWIZZLE_R:
   3839 			if(clientVersion >= 3)
   3840 			{
   3841 				*params = (GLint)texture->getSwizzleR();
   3842 				break;
   3843 			}
   3844 			else return error(GL_INVALID_ENUM);
   3845 		case GL_TEXTURE_SWIZZLE_G:
   3846 			if(clientVersion >= 3)
   3847 			{
   3848 				*params = (GLint)texture->getSwizzleG();
   3849 				break;
   3850 			}
   3851 			else return error(GL_INVALID_ENUM);
   3852 		case GL_TEXTURE_SWIZZLE_B:
   3853 			if(clientVersion >= 3)
   3854 			{
   3855 				*params = (GLint)texture->getSwizzleB();
   3856 				break;
   3857 			}
   3858 			else return error(GL_INVALID_ENUM);
   3859 		case GL_TEXTURE_SWIZZLE_A:
   3860 			if(clientVersion >= 3)
   3861 			{
   3862 				*params = (GLint)texture->getSwizzleA();
   3863 				break;
   3864 			}
   3865 			else return error(GL_INVALID_ENUM);
   3866 		default:
   3867 			return error(GL_INVALID_ENUM);
   3868 		}
   3869 	}
   3870 }
   3871 
   3872 void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
   3873 {
   3874 	TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
   3875 	      program, location, bufSize, params);
   3876 
   3877 	if(bufSize < 0)
   3878 	{
   3879 		return error(GL_INVALID_VALUE);
   3880 	}
   3881 
   3882 	es2::Context *context = es2::getContext();
   3883 
   3884 	if(context)
   3885 	{
   3886 		es2::Program *programObject = context->getProgram(program);
   3887 
   3888 		if(!programObject)
   3889 		{
   3890 			if(context->getShader(program))
   3891 			{
   3892 				return error(GL_INVALID_OPERATION);
   3893 			}
   3894 			else
   3895 			{
   3896 				return error(GL_INVALID_VALUE);
   3897 			}
   3898 		}
   3899 
   3900 		if(!programObject->isLinked())
   3901 		{
   3902 			return error(GL_INVALID_OPERATION);
   3903 		}
   3904 
   3905 		if(!programObject->getUniformfv(location, &bufSize, params))
   3906 		{
   3907 			return error(GL_INVALID_OPERATION);
   3908 		}
   3909 	}
   3910 }
   3911 
   3912 void GetUniformfv(GLuint program, GLint location, GLfloat* params)
   3913 {
   3914 	TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
   3915 
   3916 	es2::Context *context = es2::getContext();
   3917 
   3918 	if(context)
   3919 	{
   3920 		es2::Program *programObject = context->getProgram(program);
   3921 
   3922 		if(!programObject)
   3923 		{
   3924 			if(context->getShader(program))
   3925 			{
   3926 				return error(GL_INVALID_OPERATION);
   3927 			}
   3928 			else
   3929 			{
   3930 				return error(GL_INVALID_VALUE);
   3931 			}
   3932 		}
   3933 
   3934 		if(!programObject->isLinked())
   3935 		{
   3936 			return error(GL_INVALID_OPERATION);
   3937 		}
   3938 
   3939 		if(!programObject->getUniformfv(location, nullptr, params))
   3940 		{
   3941 			return error(GL_INVALID_OPERATION);
   3942 		}
   3943 	}
   3944 }
   3945 
   3946 void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
   3947 {
   3948 	TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
   3949 	      program, location, bufSize, params);
   3950 
   3951 	if(bufSize < 0)
   3952 	{
   3953 		return error(GL_INVALID_VALUE);
   3954 	}
   3955 
   3956 	es2::Context *context = es2::getContext();
   3957 
   3958 	if(context)
   3959 	{
   3960 		es2::Program *programObject = context->getProgram(program);
   3961 
   3962 		if(!programObject)
   3963 		{
   3964 			if(context->getShader(program))
   3965 			{
   3966 				return error(GL_INVALID_OPERATION);
   3967 			}
   3968 			else
   3969 			{
   3970 				return error(GL_INVALID_VALUE);
   3971 			}
   3972 		}
   3973 
   3974 		if(!programObject->isLinked())
   3975 		{
   3976 			return error(GL_INVALID_OPERATION);
   3977 		}
   3978 
   3979 		if(!programObject->getUniformiv(location, &bufSize, params))
   3980 		{
   3981 			return error(GL_INVALID_OPERATION);
   3982 		}
   3983 	}
   3984 }
   3985 
   3986 void GetUniformiv(GLuint program, GLint location, GLint* params)
   3987 {
   3988 	TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
   3989 
   3990 	es2::Context *context = es2::getContext();
   3991 
   3992 	if(context)
   3993 	{
   3994 		es2::Program *programObject = context->getProgram(program);
   3995 
   3996 		if(!programObject)
   3997 		{
   3998 			if(context->getShader(program))
   3999 			{
   4000 				return error(GL_INVALID_OPERATION);
   4001 			}
   4002 			else
   4003 			{
   4004 				return error(GL_INVALID_VALUE);
   4005 			}
   4006 		}
   4007 
   4008 		if(!programObject->isLinked())
   4009 		{
   4010 			return error(GL_INVALID_OPERATION);
   4011 		}
   4012 
   4013 		if(!programObject->getUniformiv(location, nullptr, params))
   4014 		{
   4015 			return error(GL_INVALID_OPERATION);
   4016 		}
   4017 	}
   4018 }
   4019 
   4020 int GetUniformLocation(GLuint program, const GLchar* name)
   4021 {
   4022 	TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
   4023 
   4024 	es2::Context *context = es2::getContext();
   4025 
   4026 	if(strstr(name, "gl_") == name)
   4027 	{
   4028 		return -1;
   4029 	}
   4030 
   4031 	if(context)
   4032 	{
   4033 		es2::Program *programObject = context->getProgram(program);
   4034 
   4035 		if(!programObject)
   4036 		{
   4037 			if(context->getShader(program))
   4038 			{
   4039 				return error(GL_INVALID_OPERATION, -1);
   4040 			}
   4041 			else
   4042 			{
   4043 				return error(GL_INVALID_VALUE, -1);
   4044 			}
   4045 		}
   4046 
   4047 		if(!programObject->isLinked())
   4048 		{
   4049 			return error(GL_INVALID_OPERATION, -1);
   4050 		}
   4051 
   4052 		return programObject->getUniformLocation(name);
   4053 	}
   4054 
   4055 	return -1;
   4056 }
   4057 
   4058 void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
   4059 {
   4060 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
   4061 
   4062 	es2::Context *context = es2::getContext();
   4063 
   4064 	if(context)
   4065 	{
   4066 		if(index >= es2::MAX_VERTEX_ATTRIBS)
   4067 		{
   4068 			return error(GL_INVALID_VALUE);
   4069 		}
   4070 
   4071 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
   4072 
   4073 		GLint clientVersion = context->getClientVersion();
   4074 
   4075 		switch(pname)
   4076 		{
   4077 		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
   4078 			*params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
   4079 			break;
   4080 		case GL_VERTEX_ATTRIB_ARRAY_SIZE:
   4081 			*params = (GLfloat)attribState.mSize;
   4082 			break;
   4083 		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
   4084 			*params = (GLfloat)attribState.mStride;
   4085 			break;
   4086 		case GL_VERTEX_ATTRIB_ARRAY_TYPE:
   4087 			*params = (GLfloat)attribState.mType;
   4088 			break;
   4089 		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
   4090 			*params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
   4091 			break;
   4092 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
   4093 			*params = (GLfloat)attribState.mBoundBuffer.name();
   4094 			break;
   4095 		case GL_CURRENT_VERTEX_ATTRIB:
   4096 			{
   4097 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
   4098 				for(int i = 0; i < 4; ++i)
   4099 				{
   4100 					params[i] = attrib.getCurrentValueF(i);
   4101 				}
   4102 			}
   4103 			break;
   4104 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
   4105 			if(clientVersion >= 3)
   4106 			{
   4107 				switch(attribState.mType)
   4108 				{
   4109 				case GL_BYTE:
   4110 				case GL_UNSIGNED_BYTE:
   4111 				case GL_SHORT:
   4112 				case GL_UNSIGNED_SHORT:
   4113 				case GL_INT:
   4114 				case GL_INT_2_10_10_10_REV:
   4115 				case GL_UNSIGNED_INT:
   4116 				case GL_FIXED:
   4117 					*params = (GLfloat)GL_TRUE;
   4118 					break;
   4119 				default:
   4120 					*params = (GLfloat)GL_FALSE;
   4121 					break;
   4122 				}
   4123 				break;
   4124 			}
   4125 			else return error(GL_INVALID_ENUM);
   4126 		default: return error(GL_INVALID_ENUM);
   4127 		}
   4128 	}
   4129 }
   4130 
   4131 void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
   4132 {
   4133 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
   4134 
   4135 	es2::Context *context = es2::getContext();
   4136 
   4137 	if(context)
   4138 	{
   4139 		if(index >= es2::MAX_VERTEX_ATTRIBS)
   4140 		{
   4141 			return error(GL_INVALID_VALUE);
   4142 		}
   4143 
   4144 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
   4145 
   4146 		GLint clientVersion = context->getClientVersion();
   4147 
   4148 		switch(pname)
   4149 		{
   4150 		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
   4151 			*params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
   4152 			break;
   4153 		case GL_VERTEX_ATTRIB_ARRAY_SIZE:
   4154 			*params = attribState.mSize;
   4155 			break;
   4156 		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
   4157 			*params = attribState.mStride;
   4158 			break;
   4159 		case GL_VERTEX_ATTRIB_ARRAY_TYPE:
   4160 			*params = attribState.mType;
   4161 			break;
   4162 		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
   4163 			*params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
   4164 			break;
   4165 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
   4166 			*params = attribState.mBoundBuffer.name();
   4167 			break;
   4168 		case GL_CURRENT_VERTEX_ATTRIB:
   4169 			{
   4170 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
   4171 				for(int i = 0; i < 4; ++i)
   4172 				{
   4173 					float currentValue = attrib.getCurrentValueF(i);
   4174 					params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
   4175 				}
   4176 			}
   4177 			break;
   4178 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
   4179 			if(clientVersion >= 3)
   4180 			{
   4181 				switch(attribState.mType)
   4182 				{
   4183 				case GL_BYTE:
   4184 				case GL_UNSIGNED_BYTE:
   4185 				case GL_SHORT:
   4186 				case GL_UNSIGNED_SHORT:
   4187 				case GL_INT:
   4188 				case GL_INT_2_10_10_10_REV:
   4189 				case GL_UNSIGNED_INT:
   4190 				case GL_FIXED:
   4191 					*params = GL_TRUE;
   4192 					break;
   4193 				default:
   4194 					*params = GL_FALSE;
   4195 					break;
   4196 				}
   4197 				break;
   4198 			}
   4199 			else return error(GL_INVALID_ENUM);
   4200 		default: return error(GL_INVALID_ENUM);
   4201 		}
   4202 	}
   4203 }
   4204 
   4205 void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
   4206 {
   4207 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
   4208 
   4209 	es2::Context *context = es2::getContext();
   4210 
   4211 	if(context)
   4212 	{
   4213 		if(index >= es2::MAX_VERTEX_ATTRIBS)
   4214 		{
   4215 			return error(GL_INVALID_VALUE);
   4216 		}
   4217 
   4218 		if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
   4219 		{
   4220 			return error(GL_INVALID_ENUM);
   4221 		}
   4222 
   4223 		*pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
   4224 	}
   4225 }
   4226 
   4227 void Hint(GLenum target, GLenum mode)
   4228 {
   4229 	TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
   4230 
   4231 	switch(mode)
   4232 	{
   4233 	case GL_FASTEST:
   4234 	case GL_NICEST:
   4235 	case GL_DONT_CARE:
   4236 		break;
   4237 	default:
   4238 		return error(GL_INVALID_ENUM);
   4239 	}
   4240 
   4241 	es2::Context *context = es2::getContext();
   4242 	switch(target)
   4243 	{
   4244 	case GL_GENERATE_MIPMAP_HINT:
   4245 		if(context) context->setGenerateMipmapHint(mode);
   4246 		break;
   4247 	case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
   4248 		if(context) context->setFragmentShaderDerivativeHint(mode);
   4249 		break;
   4250 	case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
   4251 		if(context) context->setTextureFilteringHint(mode);
   4252 		break;
   4253 	default:
   4254 		return error(GL_INVALID_ENUM);
   4255 	}
   4256 }
   4257 
   4258 GLboolean IsBuffer(GLuint buffer)
   4259 {
   4260 	TRACE("(GLuint buffer = %d)", buffer);
   4261 
   4262 	es2::Context *context = es2::getContext();
   4263 
   4264 	if(context && buffer)
   4265 	{
   4266 		es2::Buffer *bufferObject = context->getBuffer(buffer);
   4267 
   4268 		if(bufferObject)
   4269 		{
   4270 			return GL_TRUE;
   4271 		}
   4272 	}
   4273 
   4274 	return GL_FALSE;
   4275 }
   4276 
   4277 GLboolean IsEnabled(GLenum cap)
   4278 {
   4279 	TRACE("(GLenum cap = 0x%X)", cap);
   4280 
   4281 	es2::Context *context = es2::getContext();
   4282 
   4283 	if(context)
   4284 	{
   4285 		GLint clientVersion = context->getClientVersion();
   4286 
   4287 		switch(cap)
   4288 		{
   4289 		case GL_CULL_FACE:                return context->isCullFaceEnabled();
   4290 		case GL_POLYGON_OFFSET_FILL:      return context->isPolygonOffsetFillEnabled();
   4291 		case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
   4292 		case GL_SAMPLE_COVERAGE:          return context->isSampleCoverageEnabled();
   4293 		case GL_SCISSOR_TEST:             return context->isScissorTestEnabled();
   4294 		case GL_STENCIL_TEST:             return context->isStencilTestEnabled();
   4295 		case GL_DEPTH_TEST:               return context->isDepthTestEnabled();
   4296 		case GL_BLEND:                    return context->isBlendEnabled();
   4297 		case GL_DITHER:                   return context->isDitherEnabled();
   4298 		case GL_PRIMITIVE_RESTART_FIXED_INDEX:
   4299 			if(clientVersion >= 3)
   4300 			{
   4301 				return context->isPrimitiveRestartFixedIndexEnabled();
   4302 			}
   4303 			else return error(GL_INVALID_ENUM, false);
   4304 		case GL_RASTERIZER_DISCARD:
   4305 			if(clientVersion >= 3)
   4306 			{
   4307 				return context->isRasterizerDiscardEnabled();
   4308 			}
   4309 			else return error(GL_INVALID_ENUM, false);
   4310 		default:
   4311 			return error(GL_INVALID_ENUM, false);
   4312 		}
   4313 	}
   4314 
   4315 	return false;
   4316 }
   4317 
   4318 GLboolean IsFenceNV(GLuint fence)
   4319 {
   4320 	TRACE("(GLuint fence = %d)", fence);
   4321 
   4322 	es2::Context *context = es2::getContext();
   4323 
   4324 	if(context)
   4325 	{
   4326 		es2::Fence *fenceObject = context->getFence(fence);
   4327 
   4328 		if(!fenceObject)
   4329 		{
   4330 			return GL_FALSE;
   4331 		}
   4332 
   4333 		return fenceObject->isFence();
   4334 	}
   4335 
   4336 	return GL_FALSE;
   4337 }
   4338 
   4339 GLboolean IsFramebuffer(GLuint framebuffer)
   4340 {
   4341 	TRACE("(GLuint framebuffer = %d)", framebuffer);
   4342 
   4343 	es2::Context *context = es2::getContext();
   4344 
   4345 	if(context && framebuffer)
   4346 	{
   4347 		es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
   4348 
   4349 		if(framebufferObject)
   4350 		{
   4351 			return GL_TRUE;
   4352 		}
   4353 	}
   4354 
   4355 	return GL_FALSE;
   4356 }
   4357 
   4358 GLboolean IsProgram(GLuint program)
   4359 {
   4360 	TRACE("(GLuint program = %d)", program);
   4361 
   4362 	es2::Context *context = es2::getContext();
   4363 
   4364 	if(context && program)
   4365 	{
   4366 		es2::Program *programObject = context->getProgram(program);
   4367 
   4368 		if(programObject)
   4369 		{
   4370 			return GL_TRUE;
   4371 		}
   4372 	}
   4373 
   4374 	return GL_FALSE;
   4375 }
   4376 
   4377 GLboolean IsQueryEXT(GLuint name)
   4378 {
   4379 	TRACE("(GLuint name = %d)", name);
   4380 
   4381 	if(name == 0)
   4382 	{
   4383 		return GL_FALSE;
   4384 	}
   4385 
   4386 	es2::Context *context = es2::getContext();
   4387 
   4388 	if(context)
   4389 	{
   4390 		es2::Query *queryObject = context->getQuery(name);
   4391 
   4392 		if(queryObject)
   4393 		{
   4394 			return GL_TRUE;
   4395 		}
   4396 	}
   4397 
   4398 	return GL_FALSE;
   4399 }
   4400 
   4401 GLboolean IsRenderbuffer(GLuint renderbuffer)
   4402 {
   4403 	TRACE("(GLuint renderbuffer = %d)", renderbuffer);
   4404 
   4405 	es2::Context *context = es2::getContext();
   4406 
   4407 	if(context && renderbuffer)
   4408 	{
   4409 		es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
   4410 
   4411 		if(renderbufferObject)
   4412 		{
   4413 			return GL_TRUE;
   4414 		}
   4415 	}
   4416 
   4417 	return GL_FALSE;
   4418 }
   4419 
   4420 GLboolean IsShader(GLuint shader)
   4421 {
   4422 	TRACE("(GLuint shader = %d)", shader);
   4423 
   4424 	es2::Context *context = es2::getContext();
   4425 
   4426 	if(context && shader)
   4427 	{
   4428 		es2::Shader *shaderObject = context->getShader(shader);
   4429 
   4430 		if(shaderObject)
   4431 		{
   4432 			return GL_TRUE;
   4433 		}
   4434 	}
   4435 
   4436 	return GL_FALSE;
   4437 }
   4438 
   4439 GLboolean IsTexture(GLuint texture)
   4440 {
   4441 	TRACE("(GLuint texture = %d)", texture);
   4442 
   4443 	es2::Context *context = es2::getContext();
   4444 
   4445 	if(context && texture)
   4446 	{
   4447 		es2::Texture *textureObject = context->getTexture(texture);
   4448 
   4449 		if(textureObject)
   4450 		{
   4451 			return GL_TRUE;
   4452 		}
   4453 	}
   4454 
   4455 	return GL_FALSE;
   4456 }
   4457 
   4458 void LineWidth(GLfloat width)
   4459 {
   4460 	TRACE("(GLfloat width = %f)", width);
   4461 
   4462 	if(width <= 0.0f)
   4463 	{
   4464 		return error(GL_INVALID_VALUE);
   4465 	}
   4466 
   4467 	es2::Context *context = es2::getContext();
   4468 
   4469 	if(context)
   4470 	{
   4471 		context->setLineWidth(width);
   4472 	}
   4473 }
   4474 
   4475 void LinkProgram(GLuint program)
   4476 {
   4477 	TRACE("(GLuint program = %d)", program);
   4478 
   4479 	es2::Context *context = es2::getContext();
   4480 
   4481 	if(context)
   4482 	{
   4483 		es2::Program *programObject = context->getProgram(program);
   4484 
   4485 		if(!programObject)
   4486 		{
   4487 			if(context->getShader(program))
   4488 			{
   4489 				return error(GL_INVALID_OPERATION);
   4490 			}
   4491 			else
   4492 			{
   4493 				return error(GL_INVALID_VALUE);
   4494 			}
   4495 		}
   4496 
   4497 		programObject->link();
   4498 	}
   4499 }
   4500 
   4501 void PixelStorei(GLenum pname, GLint param)
   4502 {
   4503 	TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
   4504 
   4505 	es2::Context *context = es2::getContext();
   4506 
   4507 	if(context)
   4508 	{
   4509 		GLint clientVersion = context->getClientVersion();
   4510 
   4511 		switch(pname)
   4512 		{
   4513 		case GL_UNPACK_ALIGNMENT:
   4514 			if(param != 1 && param != 2 && param != 4 && param != 8)
   4515 			{
   4516 				return error(GL_INVALID_VALUE);
   4517 			}
   4518 			context->setUnpackAlignment(param);
   4519 			break;
   4520 		case GL_PACK_ALIGNMENT:
   4521 			if(param != 1 && param != 2 && param != 4 && param != 8)
   4522 			{
   4523 				return error(GL_INVALID_VALUE);
   4524 			}
   4525 			context->setPackAlignment(param);
   4526 			break;
   4527 		case GL_PACK_ROW_LENGTH:
   4528 			if(clientVersion >= 3)
   4529 			{
   4530 				if(param < 0)
   4531 				{
   4532 					return error(GL_INVALID_VALUE);
   4533 				}
   4534 				context->setPackRowLength(param);
   4535 				break;
   4536 			}
   4537 			else return error(GL_INVALID_ENUM);
   4538 		case GL_PACK_SKIP_PIXELS:
   4539 			if(clientVersion >= 3)
   4540 			{
   4541 				if(param < 0)
   4542 				{
   4543 					return error(GL_INVALID_VALUE);
   4544 				}
   4545 				context->setPackSkipPixels(param);
   4546 				break;
   4547 			}
   4548 			else return error(GL_INVALID_ENUM);
   4549 		case GL_PACK_SKIP_ROWS:
   4550 			if(clientVersion >= 3)
   4551 			{
   4552 				if(param < 0)
   4553 				{
   4554 					return error(GL_INVALID_VALUE);
   4555 				}
   4556 				context->setPackSkipRows(param);
   4557 				break;
   4558 			}
   4559 			else return error(GL_INVALID_ENUM);
   4560 		case GL_UNPACK_ROW_LENGTH:
   4561 			if(clientVersion >= 3)
   4562 			{
   4563 				if(param < 0)
   4564 				{
   4565 					return error(GL_INVALID_VALUE);
   4566 				}
   4567 				context->setUnpackRowLength(param);
   4568 				break;
   4569 			}
   4570 			else return error(GL_INVALID_ENUM);
   4571 		case GL_UNPACK_IMAGE_HEIGHT:
   4572 			if(clientVersion >= 3)
   4573 			{
   4574 				if(param < 0)
   4575 				{
   4576 					return error(GL_INVALID_VALUE);
   4577 				}
   4578 				context->setUnpackImageHeight(param);
   4579 				break;
   4580 			}
   4581 			else return error(GL_INVALID_ENUM);
   4582 		case GL_UNPACK_SKIP_PIXELS:
   4583 			if(clientVersion >= 3)
   4584 			{
   4585 				if(param < 0)
   4586 				{
   4587 					return error(GL_INVALID_VALUE);
   4588 				}
   4589 				context->setUnpackSkipPixels(param);
   4590 				break;
   4591 			}
   4592 			else return error(GL_INVALID_ENUM);
   4593 		case GL_UNPACK_SKIP_ROWS:
   4594 			if(clientVersion >= 3)
   4595 			{
   4596 				if(param < 0)
   4597 				{
   4598 					return error(GL_INVALID_VALUE);
   4599 				}
   4600 				context->setUnpackSkipRows(param);
   4601 				break;
   4602 			}
   4603 			else return error(GL_INVALID_ENUM);
   4604 		case GL_UNPACK_SKIP_IMAGES:
   4605 			if(clientVersion >= 3) {
   4606 				if(param < 0)
   4607 				{
   4608 					return error(GL_INVALID_VALUE);
   4609 				}
   4610 				context->setUnpackSkipImages(param);
   4611 				break;
   4612 			}
   4613 			else return error(GL_INVALID_ENUM);
   4614 		default:
   4615 			return error(GL_INVALID_ENUM);
   4616 		}
   4617 	}
   4618 }
   4619 
   4620 void PolygonOffset(GLfloat factor, GLfloat units)
   4621 {
   4622 	TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
   4623 
   4624 	es2::Context *context = es2::getContext();
   4625 
   4626 	if(context)
   4627 	{
   4628 		context->setPolygonOffsetParams(factor, units);
   4629 	}
   4630 }
   4631 
   4632 void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
   4633                     GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
   4634 {
   4635 	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
   4636 	      "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
   4637 	      x, y, width, height, format, type, bufSize, data);
   4638 
   4639 	if(width < 0 || height < 0 || bufSize < 0)
   4640 	{
   4641 		return error(GL_INVALID_VALUE);
   4642 	}
   4643 
   4644 	es2::Context *context = es2::getContext();
   4645 
   4646 	if(context)
   4647 	{
   4648 		context->readPixels(x, y, width, height, format, type, &bufSize, data);
   4649 	}
   4650 }
   4651 
   4652 void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
   4653 {
   4654 	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
   4655 	      "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
   4656 	      x, y, width, height, format, type,  pixels);
   4657 
   4658 	if(width < 0 || height < 0)
   4659 	{
   4660 		return error(GL_INVALID_VALUE);
   4661 	}
   4662 
   4663 	es2::Context *context = es2::getContext();
   4664 
   4665 	if(context)
   4666 	{
   4667 		context->readPixels(x, y, width, height, format, type, nullptr, pixels);
   4668 	}
   4669 }
   4670 
   4671 void ReleaseShaderCompiler(void)
   4672 {
   4673 	TRACE("()");
   4674 
   4675 	es2::Shader::releaseCompiler();
   4676 }
   4677 
   4678 void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
   4679 {
   4680 	TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
   4681 	      target, samples, internalformat, width, height);
   4682 
   4683 	switch(target)
   4684 	{
   4685 	case GL_RENDERBUFFER:
   4686 		break;
   4687 	default:
   4688 		return error(GL_INVALID_ENUM);
   4689 	}
   4690 
   4691 	if(width < 0 || height < 0 || samples < 0)
   4692 	{
   4693 		return error(GL_INVALID_VALUE);
   4694 	}
   4695 
   4696 	es2::Context *context = es2::getContext();
   4697 
   4698 	if(context)
   4699 	{
   4700 		if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
   4701 		   height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
   4702 		   samples > es2::IMPLEMENTATION_MAX_SAMPLES)
   4703 		{
   4704 			return error(GL_INVALID_VALUE);
   4705 		}
   4706 
   4707 		GLuint handle = context->getRenderbufferName();
   4708 		if(handle == 0)
   4709 		{
   4710 			return error(GL_INVALID_OPERATION);
   4711 		}
   4712 
   4713 		GLint clientVersion = context->getClientVersion();
   4714 
   4715 		if(IsColorRenderable(internalformat, clientVersion, false))
   4716 		{
   4717 			context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
   4718 		}
   4719 		else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
   4720 		{
   4721 			context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
   4722 		}
   4723 		else if(IsDepthRenderable(internalformat, clientVersion))
   4724 		{
   4725 			context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
   4726 		}
   4727 		else if(IsStencilRenderable(internalformat, clientVersion))
   4728 		{
   4729 			context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
   4730 		}
   4731 		else error(GL_INVALID_ENUM);
   4732 	}
   4733 }
   4734 
   4735 void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
   4736 {
   4737 	RenderbufferStorageMultisample(target, samples, internalformat, width, height);
   4738 }
   4739 
   4740 void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
   4741 {
   4742 	RenderbufferStorageMultisample(target, 0, internalformat, width, height);
   4743 }
   4744 
   4745 void SampleCoverage(GLclampf value, GLboolean invert)
   4746 {
   4747 	TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
   4748 
   4749 	es2::Context* context = es2::getContext();
   4750 
   4751 	if(context)
   4752 	{
   4753 		context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
   4754 	}
   4755 }
   4756 
   4757 void SetFenceNV(GLuint fence, GLenum condition)
   4758 {
   4759 	TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
   4760 
   4761 	if(condition != GL_ALL_COMPLETED_NV)
   4762 	{
   4763 		return error(GL_INVALID_ENUM);
   4764 	}
   4765 
   4766 	es2::Context *context = es2::getContext();
   4767 
   4768 	if(context)
   4769 	{
   4770 		es2::Fence *fenceObject = context->getFence(fence);
   4771 
   4772 		if(!fenceObject)
   4773 		{
   4774 			return error(GL_INVALID_OPERATION);
   4775 		}
   4776 
   4777 		fenceObject->setFence(condition);
   4778 	}
   4779 }
   4780 
   4781 void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
   4782 {
   4783 	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
   4784 
   4785 	if(width < 0 || height < 0)
   4786 	{
   4787 		return error(GL_INVALID_VALUE);
   4788 	}
   4789 
   4790 	es2::Context* context = es2::getContext();
   4791 
   4792 	if(context)
   4793 	{
   4794 		context->setScissorParams(x, y, width, height);
   4795 	}
   4796 }
   4797 
   4798 void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
   4799 {
   4800 	TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
   4801 	      "const GLvoid* binary = %p, GLsizei length = %d)",
   4802 	      n, shaders, binaryformat, binary, length);
   4803 
   4804 	// No binary shader formats are supported.
   4805 	return error(GL_INVALID_ENUM);
   4806 }
   4807 
   4808 void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
   4809 {
   4810 	TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
   4811 	      shader, count, string, length);
   4812 
   4813 	if(count < 0)
   4814 	{
   4815 		return error(GL_INVALID_VALUE);
   4816 	}
   4817 
   4818 	es2::Context *context = es2::getContext();
   4819 
   4820 	if(context)
   4821 	{
   4822 		es2::Shader *shaderObject = context->getShader(shader);
   4823 
   4824 		if(!shaderObject)
   4825 		{
   4826 			if(context->getProgram(shader))
   4827 			{
   4828 				return error(GL_INVALID_OPERATION);
   4829 			}
   4830 			else
   4831 			{
   4832 				return error(GL_INVALID_VALUE);
   4833 			}
   4834 		}
   4835 
   4836 		shaderObject->setSource(count, string, length);
   4837 	}
   4838 }
   4839 
   4840 void StencilFunc(GLenum func, GLint ref, GLuint mask)
   4841 {
   4842 	glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
   4843 }
   4844 
   4845 void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
   4846 {
   4847 	TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
   4848 
   4849 	switch(face)
   4850 	{
   4851 	case GL_FRONT:
   4852 	case GL_BACK:
   4853 	case GL_FRONT_AND_BACK:
   4854 		break;
   4855 	default:
   4856 		return error(GL_INVALID_ENUM);
   4857 	}
   4858 
   4859 	switch(func)
   4860 	{
   4861 	case GL_NEVER:
   4862 	case GL_ALWAYS:
   4863 	case GL_LESS:
   4864 	case GL_LEQUAL:
   4865 	case GL_EQUAL:
   4866 	case GL_GEQUAL:
   4867 	case GL_GREATER:
   4868 	case GL_NOTEQUAL:
   4869 		break;
   4870 	default:
   4871 		return error(GL_INVALID_ENUM);
   4872 	}
   4873 
   4874 	es2::Context *context = es2::getContext();
   4875 
   4876 	if(context)
   4877 	{
   4878 		if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
   4879 		{
   4880 			context->setStencilParams(func, ref, mask);
   4881 		}
   4882 
   4883 		if(face == GL_BACK || face == GL_FRONT_AND_BACK)
   4884 		{
   4885 			context->setStencilBackParams(func, ref, mask);
   4886 		}
   4887 	}
   4888 }
   4889 
   4890 void StencilMask(GLuint mask)
   4891 {
   4892 	glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
   4893 }
   4894 
   4895 void StencilMaskSeparate(GLenum face, GLuint mask)
   4896 {
   4897 	TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
   4898 
   4899 	switch(face)
   4900 	{
   4901 	case GL_FRONT:
   4902 	case GL_BACK:
   4903 	case GL_FRONT_AND_BACK:
   4904 		break;
   4905 	default:
   4906 		return error(GL_INVALID_ENUM);
   4907 	}
   4908 
   4909 	es2::Context *context = es2::getContext();
   4910 
   4911 	if(context)
   4912 	{
   4913 		if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
   4914 		{
   4915 			context->setStencilWritemask(mask);
   4916 		}
   4917 
   4918 		if(face == GL_BACK || face == GL_FRONT_AND_BACK)
   4919 		{
   4920 			context->setStencilBackWritemask(mask);
   4921 		}
   4922 	}
   4923 }
   4924 
   4925 void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
   4926 {
   4927 	glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
   4928 }
   4929 
   4930 void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
   4931 {
   4932 	TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
   4933 	      face, fail, zfail, zpass);
   4934 
   4935 	switch(face)
   4936 	{
   4937 	case GL_FRONT:
   4938 	case GL_BACK:
   4939 	case GL_FRONT_AND_BACK:
   4940 		break;
   4941 	default:
   4942 		return error(GL_INVALID_ENUM);
   4943 	}
   4944 
   4945 	switch(fail)
   4946 	{
   4947 	case GL_ZERO:
   4948 	case GL_KEEP:
   4949 	case GL_REPLACE:
   4950 	case GL_INCR:
   4951 	case GL_DECR:
   4952 	case GL_INVERT:
   4953 	case GL_INCR_WRAP:
   4954 	case GL_DECR_WRAP:
   4955 		break;
   4956 	default:
   4957 		return error(GL_INVALID_ENUM);
   4958 	}
   4959 
   4960 	switch(zfail)
   4961 	{
   4962 	case GL_ZERO:
   4963 	case GL_KEEP:
   4964 	case GL_REPLACE:
   4965 	case GL_INCR:
   4966 	case GL_DECR:
   4967 	case GL_INVERT:
   4968 	case GL_INCR_WRAP:
   4969 	case GL_DECR_WRAP:
   4970 		break;
   4971 	default:
   4972 		return error(GL_INVALID_ENUM);
   4973 	}
   4974 
   4975 	switch(zpass)
   4976 	{
   4977 	case GL_ZERO:
   4978 	case GL_KEEP:
   4979 	case GL_REPLACE:
   4980 	case GL_INCR:
   4981 	case GL_DECR:
   4982 	case GL_INVERT:
   4983 	case GL_INCR_WRAP:
   4984 	case GL_DECR_WRAP:
   4985 		break;
   4986 	default:
   4987 		return error(GL_INVALID_ENUM);
   4988 	}
   4989 
   4990 	es2::Context *context = es2::getContext();
   4991 
   4992 	if(context)
   4993 	{
   4994 		if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
   4995 		{
   4996 			context->setStencilOperations(fail, zfail, zpass);
   4997 		}
   4998 
   4999 		if(face == GL_BACK || face == GL_FRONT_AND_BACK)
   5000 		{
   5001 			context->setStencilBackOperations(fail, zfail, zpass);
   5002 		}
   5003 	}
   5004 }
   5005 
   5006 GLboolean TestFenceNV(GLuint fence)
   5007 {
   5008 	TRACE("(GLuint fence = %d)", fence);
   5009 
   5010 	es2::Context *context = es2::getContext();
   5011 
   5012 	if(context)
   5013 	{
   5014 		es2::Fence *fenceObject = context->getFence(fence);
   5015 
   5016 		if(!fenceObject)
   5017 		{
   5018 			return error(GL_INVALID_OPERATION, GL_TRUE);
   5019 		}
   5020 
   5021 		return fenceObject->testFence();
   5022 	}
   5023 
   5024 	return GL_TRUE;
   5025 }
   5026 
   5027 void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
   5028                 GLint border, GLenum format, GLenum type, const GLvoid* data)
   5029 {
   5030 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
   5031 	      "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data =  %p)",
   5032 	      target, level, internalformat, width, height, border, format, type, data);
   5033 
   5034 	if(!validImageSize(level, width, height))
   5035 	{
   5036 		return error(GL_INVALID_VALUE);
   5037 	}
   5038 
   5039 	es2::Context *context = es2::getContext();
   5040 
   5041 	if(context)
   5042 	{
   5043 		GLint clientVersion = context->getClientVersion();
   5044 		if(clientVersion < 3)
   5045 		{
   5046 			if(internalformat != (GLint)format)
   5047 			{
   5048 				return error(GL_INVALID_OPERATION);
   5049 			}
   5050 		}
   5051 
   5052 		GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
   5053 		if(validationError != GL_NONE)
   5054 		{
   5055 			return error(validationError);
   5056 		}
   5057 
   5058 		if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
   5059 		{
   5060 			return;
   5061 		}
   5062 
   5063 		if(border != 0)
   5064 		{
   5065 			return error(GL_INVALID_VALUE);
   5066 		}
   5067 
   5068 		switch(target)
   5069 		{
   5070 		case GL_TEXTURE_2D:
   5071 			if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
   5072 			   height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
   5073 			{
   5074 				return error(GL_INVALID_VALUE);
   5075 			}
   5076 			break;
   5077 		case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   5078 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   5079 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   5080 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   5081 		case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   5082 		case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   5083 			if(width != height)
   5084 			{
   5085 				return error(GL_INVALID_VALUE);
   5086 			}
   5087 
   5088 			if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
   5089 			   height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
   5090 			{
   5091 				return error(GL_INVALID_VALUE);
   5092 			}
   5093 			break;
   5094 		default:
   5095 			return error(GL_INVALID_ENUM);
   5096 		}
   5097 
   5098 		GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
   5099 
   5100 		if(target == GL_TEXTURE_2D)
   5101 		{
   5102 			es2::Texture2D *texture = context->getTexture2D();
   5103 
   5104 			if(!texture)
   5105 			{
   5106 				return error(GL_INVALID_OPERATION);
   5107 			}
   5108 
   5109 			texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data));
   5110 		}
   5111 		else
   5112 		{
   5113 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
   5114 
   5115 			if(!texture)
   5116 			{
   5117 				return error(GL_INVALID_OPERATION);
   5118 			}
   5119 
   5120 			texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data));
   5121 		}
   5122 	}
   5123 }
   5124 
   5125 void TexParameterf(GLenum target, GLenum pname, GLfloat param)
   5126 {
   5127 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
   5128 
   5129 	es2::Context *context = es2::getContext();
   5130 
   5131 	if(context)
   5132 	{
   5133 		es2::Texture *texture;
   5134 
   5135 		GLint clientVersion = context->getClientVersion();
   5136 
   5137 		switch(target)
   5138 		{
   5139 		case GL_TEXTURE_2D:
   5140 			texture = context->getTexture2D();
   5141 			break;
   5142 		case GL_TEXTURE_2D_ARRAY:
   5143 			if(clientVersion < 3)
   5144 			{
   5145 				return error(GL_INVALID_ENUM);
   5146 			}
   5147 			else
   5148 			{
   5149 				texture = context->getTexture2DArray();
   5150 			}
   5151 			break;
   5152 		case GL_TEXTURE_3D_OES:
   5153 			texture = context->getTexture3D();
   5154 			break;
   5155 		case GL_TEXTURE_CUBE_MAP:
   5156 			texture = context->getTextureCubeMap();
   5157 			break;
   5158 		case GL_TEXTURE_EXTERNAL_OES:
   5159 			texture = context->getTextureExternal();
   5160 			break;
   5161 		default:
   5162 			return error(GL_INVALID_ENUM);
   5163 		}
   5164 
   5165 		switch(pname)
   5166 		{
   5167 		case GL_TEXTURE_WRAP_S:
   5168 			if(!texture->setWrapS((GLenum)param))
   5169 			{
   5170 				return error(GL_INVALID_ENUM);
   5171 			}
   5172 			break;
   5173 		case GL_TEXTURE_WRAP_T:
   5174 			if(!texture->setWrapT((GLenum)param))
   5175 			{
   5176 				return error(GL_INVALID_ENUM);
   5177 			}
   5178 			break;
   5179 		case GL_TEXTURE_WRAP_R_OES:
   5180 			if(!texture->setWrapR((GLenum)param))
   5181 			{
   5182 				return error(GL_INVALID_ENUM);
   5183 			}
   5184 			break;
   5185 		case GL_TEXTURE_MIN_FILTER:
   5186 			if(!texture->setMinFilter((GLenum)param))
   5187 			{
   5188 				return error(GL_INVALID_ENUM);
   5189 			}
   5190 			break;
   5191 		case GL_TEXTURE_MAG_FILTER:
   5192 			if(!texture->setMagFilter((GLenum)param))
   5193 			{
   5194 				return error(GL_INVALID_ENUM);
   5195 			}
   5196 			break;
   5197 		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   5198 			if(!texture->setMaxAnisotropy(param))
   5199 			{
   5200 				return error(GL_INVALID_VALUE);
   5201 			}
   5202 			break;
   5203 		case GL_TEXTURE_BASE_LEVEL:
   5204 			if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
   5205 			{
   5206 				return error(GL_INVALID_VALUE);
   5207 			}
   5208 			break;
   5209 		case GL_TEXTURE_COMPARE_FUNC:
   5210 			if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
   5211 			{
   5212 				return error(GL_INVALID_VALUE);
   5213 			}
   5214 			break;
   5215 		case GL_TEXTURE_COMPARE_MODE:
   5216 			if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
   5217 			{
   5218 				return error(GL_INVALID_VALUE);
   5219 			}
   5220 			break;
   5221 		case GL_TEXTURE_MAX_LEVEL:
   5222 			if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
   5223 			{
   5224 				return error(GL_INVALID_VALUE);
   5225 			}
   5226 			break;
   5227 		case GL_TEXTURE_MAX_LOD:
   5228 			if(clientVersion < 3 || !texture->setMaxLOD(param))
   5229 			{
   5230 				return error(GL_INVALID_VALUE);
   5231 			}
   5232 			break;
   5233 		case GL_TEXTURE_MIN_LOD:
   5234 			if(clientVersion < 3 || !texture->setMinLOD(param))
   5235 			{
   5236 				return error(GL_INVALID_VALUE);
   5237 			}
   5238 			break;
   5239 		case GL_TEXTURE_SWIZZLE_R:
   5240 			if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
   5241 			{
   5242 				return error(GL_INVALID_VALUE);
   5243 			}
   5244 			break;
   5245 		case GL_TEXTURE_SWIZZLE_G:
   5246 			if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
   5247 			{
   5248 				return error(GL_INVALID_VALUE);
   5249 			}
   5250 			break;
   5251 		case GL_TEXTURE_SWIZZLE_B:
   5252 			if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
   5253 			{
   5254 				return error(GL_INVALID_VALUE);
   5255 			}
   5256 			break;
   5257 		case GL_TEXTURE_SWIZZLE_A:
   5258 			if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
   5259 			{
   5260 				return error(GL_INVALID_VALUE);
   5261 			}
   5262 			break;
   5263 		default:
   5264 			return error(GL_INVALID_ENUM);
   5265 		}
   5266 	}
   5267 }
   5268 
   5269 void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
   5270 {
   5271 	glTexParameterf(target, pname, *params);
   5272 }
   5273 
   5274 void TexParameteri(GLenum target, GLenum pname, GLint param)
   5275 {
   5276 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
   5277 
   5278 	es2::Context *context = es2::getContext();
   5279 
   5280 	if(context)
   5281 	{
   5282 		es2::Texture *texture;
   5283 
   5284 		GLint clientVersion = context->getClientVersion();
   5285 
   5286 		switch(target)
   5287 		{
   5288 		case GL_TEXTURE_2D:
   5289 			texture = context->getTexture2D();
   5290 			break;
   5291 		case GL_TEXTURE_2D_ARRAY:
   5292 			if(clientVersion < 3)
   5293 			{
   5294 				return error(GL_INVALID_ENUM);
   5295 			}
   5296 			else
   5297 			{
   5298 				texture = context->getTexture2DArray();
   5299 			}
   5300 			break;
   5301 		case GL_TEXTURE_3D_OES:
   5302 			texture = context->getTexture3D();
   5303 			break;
   5304 		case GL_TEXTURE_CUBE_MAP:
   5305 			texture = context->getTextureCubeMap();
   5306 			break;
   5307 		case GL_TEXTURE_EXTERNAL_OES:
   5308 			texture = context->getTextureExternal();
   5309 			break;
   5310 		default:
   5311 			return error(GL_INVALID_ENUM);
   5312 		}
   5313 
   5314 		switch(pname)
   5315 		{
   5316 		case GL_TEXTURE_WRAP_S:
   5317 			if(!texture->setWrapS((GLenum)param))
   5318 			{
   5319 				return error(GL_INVALID_ENUM);
   5320 			}
   5321 			break;
   5322 		case GL_TEXTURE_WRAP_T:
   5323 			if(!texture->setWrapT((GLenum)param))
   5324 			{
   5325 				return error(GL_INVALID_ENUM);
   5326 			}
   5327 			break;
   5328 		case GL_TEXTURE_WRAP_R_OES:
   5329 			if(!texture->setWrapR((GLenum)param))
   5330 			{
   5331 				return error(GL_INVALID_ENUM);
   5332 			}
   5333 			break;
   5334 		case GL_TEXTURE_MIN_FILTER:
   5335 			if(!texture->setMinFilter((GLenum)param))
   5336 			{
   5337 				return error(GL_INVALID_ENUM);
   5338 			}
   5339 			break;
   5340 		case GL_TEXTURE_MAG_FILTER:
   5341 			if(!texture->setMagFilter((GLenum)param))
   5342 			{
   5343 				return error(GL_INVALID_ENUM);
   5344 			}
   5345 			break;
   5346 		case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   5347 			if(!texture->setMaxAnisotropy((GLfloat)param))
   5348 			{
   5349 				return error(GL_INVALID_VALUE);
   5350 			}
   5351 			break;
   5352 		case GL_TEXTURE_BASE_LEVEL:
   5353 			if(clientVersion < 3 || !texture->setBaseLevel(param))
   5354 			{
   5355 				return error(GL_INVALID_VALUE);
   5356 			}
   5357 			break;
   5358 		case GL_TEXTURE_COMPARE_FUNC:
   5359 			if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
   5360 			{
   5361 				return error(GL_INVALID_VALUE);
   5362 			}
   5363 			break;
   5364 		case GL_TEXTURE_COMPARE_MODE:
   5365 			if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
   5366 			{
   5367 				return error(GL_INVALID_VALUE);
   5368 			}
   5369 			break;
   5370 		case GL_TEXTURE_MAX_LEVEL:
   5371 			if(clientVersion < 3 || !texture->setMaxLevel(param))
   5372 			{
   5373 				return error(GL_INVALID_VALUE);
   5374 			}
   5375 			break;
   5376 		case GL_TEXTURE_MAX_LOD:
   5377 			if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
   5378 			{
   5379 				return error(GL_INVALID_VALUE);
   5380 			}
   5381 			break;
   5382 		case GL_TEXTURE_MIN_LOD:
   5383 			if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
   5384 			{
   5385 				return error(GL_INVALID_VALUE);
   5386 			}
   5387 			break;
   5388 		case GL_TEXTURE_SWIZZLE_R:
   5389 			if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
   5390 			{
   5391 				return error(GL_INVALID_VALUE);
   5392 			}
   5393 			break;
   5394 		case GL_TEXTURE_SWIZZLE_G:
   5395 			if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
   5396 			{
   5397 				return error(GL_INVALID_VALUE);
   5398 			}
   5399 			break;
   5400 		case GL_TEXTURE_SWIZZLE_B:
   5401 			if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
   5402 			{
   5403 				return error(GL_INVALID_VALUE);
   5404 			}
   5405 			break;
   5406 		case GL_TEXTURE_SWIZZLE_A:
   5407 			if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
   5408 			{
   5409 				return error(GL_INVALID_VALUE);
   5410 			}
   5411 			break;
   5412 		default:
   5413 			return error(GL_INVALID_ENUM);
   5414 		}
   5415 	}
   5416 }
   5417 
   5418 void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
   5419 {
   5420 	glTexParameteri(target, pname, *params);
   5421 }
   5422 
   5423 void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
   5424                    GLenum format, GLenum type, const GLvoid* data)
   5425 {
   5426 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
   5427 	      "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
   5428 	      "const GLvoid* data = %p)",
   5429 	      target, level, xoffset, yoffset, width, height, format, type, data);
   5430 
   5431 	if(!es2::IsTextureTarget(target))
   5432 	{
   5433 		return error(GL_INVALID_ENUM);
   5434 	}
   5435 
   5436 	if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   5437 	{
   5438 		return error(GL_INVALID_VALUE);
   5439 	}
   5440 
   5441 	if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
   5442 	{
   5443 		return error(GL_INVALID_VALUE);
   5444 	}
   5445 
   5446 	if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
   5447 	{
   5448 		return error(GL_INVALID_VALUE);
   5449 	}
   5450 
   5451 	if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
   5452 	{
   5453 		return;
   5454 	}
   5455 
   5456 	if(width == 0 || height == 0)
   5457 	{
   5458 		return;
   5459 	}
   5460 
   5461 	es2::Context *context = es2::getContext();
   5462 
   5463 	if(context)
   5464 	{
   5465 		GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
   5466 
   5467 		if(target == GL_TEXTURE_2D)
   5468 		{
   5469 			es2::Texture2D *texture = context->getTexture2D();
   5470 
   5471 			GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
   5472 
   5473 			if(validationError == GL_NONE)
   5474 			{
   5475 				texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data));
   5476 			}
   5477 			else
   5478 			{
   5479 				return error(validationError);
   5480 			}
   5481 		}
   5482 		else if(es2::IsCubemapTextureTarget(target))
   5483 		{
   5484 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
   5485 
   5486 			GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
   5487 
   5488 			if(validationError == GL_NONE)
   5489 			{
   5490 				texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data));
   5491 			}
   5492 			else
   5493 			{
   5494 				return error(validationError);
   5495 			}
   5496 		}
   5497 		else UNREACHABLE(target);
   5498 	}
   5499 }
   5500 
   5501 void Uniform1f(GLint location, GLfloat x)
   5502 {
   5503 	glUniform1fv(location, 1, &x);
   5504 }
   5505 
   5506 void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
   5507 {
   5508 	TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
   5509 
   5510 	if(count < 0)
   5511 	{
   5512 		return error(GL_INVALID_VALUE);
   5513 	}
   5514 
   5515 	if(location == -1)
   5516 	{
   5517 		return;
   5518 	}
   5519 
   5520 	es2::Context *context = es2::getContext();
   5521 
   5522 	if(context)
   5523 	{
   5524 		es2::Program *program = context->getCurrentProgram();
   5525 
   5526 		if(!program)
   5527 		{
   5528 			return error(GL_INVALID_OPERATION);
   5529 		}
   5530 
   5531 		if(!program->setUniform1fv(location, count, v))
   5532 		{
   5533 			return error(GL_INVALID_OPERATION);
   5534 		}
   5535 	}
   5536 }
   5537 
   5538 void Uniform1i(GLint location, GLint x)
   5539 {
   5540 	glUniform1iv(location, 1, &x);
   5541 }
   5542 
   5543 void Uniform1iv(GLint location, GLsizei count, const GLint* v)
   5544 {
   5545 	TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
   5546 
   5547 	if(count < 0)
   5548 	{
   5549 		return error(GL_INVALID_VALUE);
   5550 	}
   5551 
   5552 	if(location == -1)
   5553 	{
   5554 		return;
   5555 	}
   5556 
   5557 	es2::Context *context = es2::getContext();
   5558 
   5559 	if(context)
   5560 	{
   5561 		es2::Program *program = context->getCurrentProgram();
   5562 
   5563 		if(!program)
   5564 		{
   5565 			return error(GL_INVALID_OPERATION);
   5566 		}
   5567 
   5568 		if(!program->setUniform1iv(location, count, v))
   5569 		{
   5570 			return error(GL_INVALID_OPERATION);
   5571 		}
   5572 	}
   5573 }
   5574 
   5575 void Uniform2f(GLint location, GLfloat x, GLfloat y)
   5576 {
   5577 	GLfloat xy[2] = {x, y};
   5578 
   5579 	glUniform2fv(location, 1, (GLfloat*)&xy);
   5580 }
   5581 
   5582 void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
   5583 {
   5584 	TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
   5585 
   5586 	if(count < 0)
   5587 	{
   5588 		return error(GL_INVALID_VALUE);
   5589 	}
   5590 
   5591 	if(location == -1)
   5592 	{
   5593 		return;
   5594 	}
   5595 
   5596 	es2::Context *context = es2::getContext();
   5597 
   5598 	if(context)
   5599 	{
   5600 		es2::Program *program = context->getCurrentProgram();
   5601 
   5602 		if(!program)
   5603 		{
   5604 			return error(GL_INVALID_OPERATION);
   5605 		}
   5606 
   5607 		if(!program->setUniform2fv(location, count, v))
   5608 		{
   5609 			return error(GL_INVALID_OPERATION);
   5610 		}
   5611 	}
   5612 }
   5613 
   5614 void Uniform2i(GLint location, GLint x, GLint y)
   5615 {
   5616 	GLint xy[4] = {x, y};
   5617 
   5618 	glUniform2iv(location, 1, (GLint*)&xy);
   5619 }
   5620 
   5621 void Uniform2iv(GLint location, GLsizei count, const GLint* v)
   5622 {
   5623 	TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
   5624 
   5625 	if(count < 0)
   5626 	{
   5627 		return error(GL_INVALID_VALUE);
   5628 	}
   5629 
   5630 	if(location == -1)
   5631 	{
   5632 		return;
   5633 	}
   5634 
   5635 	es2::Context *context = es2::getContext();
   5636 
   5637 	if(context)
   5638 	{
   5639 		es2::Program *program = context->getCurrentProgram();
   5640 
   5641 		if(!program)
   5642 		{
   5643 			return error(GL_INVALID_OPERATION);
   5644 		}
   5645 
   5646 		if(!program->setUniform2iv(location, count, v))
   5647 		{
   5648 			return error(GL_INVALID_OPERATION);
   5649 		}
   5650 	}
   5651 }
   5652 
   5653 void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
   5654 {
   5655 	GLfloat xyz[3] = {x, y, z};
   5656 
   5657 	glUniform3fv(location, 1, (GLfloat*)&xyz);
   5658 }
   5659 
   5660 void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
   5661 {
   5662 	TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
   5663 
   5664 	if(count < 0)
   5665 	{
   5666 		return error(GL_INVALID_VALUE);
   5667 	}
   5668 
   5669 	if(location == -1)
   5670 	{
   5671 		return;
   5672 	}
   5673 
   5674 	es2::Context *context = es2::getContext();
   5675 
   5676 	if(context)
   5677 	{
   5678 		es2::Program *program = context->getCurrentProgram();
   5679 
   5680 		if(!program)
   5681 		{
   5682 			return error(GL_INVALID_OPERATION);
   5683 		}
   5684 
   5685 		if(!program->setUniform3fv(location, count, v))
   5686 		{
   5687 			return error(GL_INVALID_OPERATION);
   5688 		}
   5689 	}
   5690 }
   5691 
   5692 void Uniform3i(GLint location, GLint x, GLint y, GLint z)
   5693 {
   5694 	GLint xyz[3] = {x, y, z};
   5695 
   5696 	glUniform3iv(location, 1, (GLint*)&xyz);
   5697 }
   5698 
   5699 void Uniform3iv(GLint location, GLsizei count, const GLint* v)
   5700 {
   5701 	TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
   5702 
   5703 	if(count < 0)
   5704 	{
   5705 		return error(GL_INVALID_VALUE);
   5706 	}
   5707 
   5708 	if(location == -1)
   5709 	{
   5710 		return;
   5711 	}
   5712 
   5713 	es2::Context *context = es2::getContext();
   5714 
   5715 	if(context)
   5716 	{
   5717 		es2::Program *program = context->getCurrentProgram();
   5718 
   5719 		if(!program)
   5720 		{
   5721 			return error(GL_INVALID_OPERATION);
   5722 		}
   5723 
   5724 		if(!program->setUniform3iv(location, count, v))
   5725 		{
   5726 			return error(GL_INVALID_OPERATION);
   5727 		}
   5728 	}
   5729 }
   5730 
   5731 void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5732 {
   5733 	GLfloat xyzw[4] = {x, y, z, w};
   5734 
   5735 	glUniform4fv(location, 1, (GLfloat*)&xyzw);
   5736 }
   5737 
   5738 void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
   5739 {
   5740 	TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
   5741 
   5742 	if(count < 0)
   5743 	{
   5744 		return error(GL_INVALID_VALUE);
   5745 	}
   5746 
   5747 	if(location == -1)
   5748 	{
   5749 		return;
   5750 	}
   5751 
   5752 	es2::Context *context = es2::getContext();
   5753 
   5754 	if(context)
   5755 	{
   5756 		es2::Program *program = context->getCurrentProgram();
   5757 
   5758 		if(!program)
   5759 		{
   5760 			return error(GL_INVALID_OPERATION);
   5761 		}
   5762 
   5763 		if(!program->setUniform4fv(location, count, v))
   5764 		{
   5765 			return error(GL_INVALID_OPERATION);
   5766 		}
   5767 	}
   5768 }
   5769 
   5770 void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
   5771 {
   5772 	GLint xyzw[4] = {x, y, z, w};
   5773 
   5774 	glUniform4iv(location, 1, (GLint*)&xyzw);
   5775 }
   5776 
   5777 void Uniform4iv(GLint location, GLsizei count, const GLint* v)
   5778 {
   5779 	TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
   5780 
   5781 	if(count < 0)
   5782 	{
   5783 		return error(GL_INVALID_VALUE);
   5784 	}
   5785 
   5786 	if(location == -1)
   5787 	{
   5788 		return;
   5789 	}
   5790 
   5791 	es2::Context *context = es2::getContext();
   5792 
   5793 	if(context)
   5794 	{
   5795 		es2::Program *program = context->getCurrentProgram();
   5796 
   5797 		if(!program)
   5798 		{
   5799 			return error(GL_INVALID_OPERATION);
   5800 		}
   5801 
   5802 		if(!program->setUniform4iv(location, count, v))
   5803 		{
   5804 			return error(GL_INVALID_OPERATION);
   5805 		}
   5806 	}
   5807 }
   5808 
   5809 void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   5810 {
   5811 	TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
   5812 	      location, count, transpose, value);
   5813 
   5814 	if(count < 0)
   5815 	{
   5816 		return error(GL_INVALID_VALUE);
   5817 	}
   5818 
   5819 	if(location == -1)
   5820 	{
   5821 		return;
   5822 	}
   5823 
   5824 	es2::Context *context = es2::getContext();
   5825 
   5826 	if(context)
   5827 	{
   5828 		if(context->getClientVersion() < 3 && transpose != GL_FALSE)
   5829 		{
   5830 			return error(GL_INVALID_VALUE);
   5831 		}
   5832 
   5833 		es2::Program *program = context->getCurrentProgram();
   5834 
   5835 		if(!program)
   5836 		{
   5837 			return error(GL_INVALID_OPERATION);
   5838 		}
   5839 
   5840 		if(!program->setUniformMatrix2fv(location, count, transpose, value))
   5841 		{
   5842 			return error(GL_INVALID_OPERATION);
   5843 		}
   5844 	}
   5845 }
   5846 
   5847 void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   5848 {
   5849 	TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
   5850 	      location, count, transpose, value);
   5851 
   5852 	if(count < 0)
   5853 	{
   5854 		return error(GL_INVALID_VALUE);
   5855 	}
   5856 
   5857 	if(location == -1)
   5858 	{
   5859 		return;
   5860 	}
   5861 
   5862 	es2::Context *context = es2::getContext();
   5863 
   5864 	if(context)
   5865 	{
   5866 		if(context->getClientVersion() < 3 && transpose != GL_FALSE)
   5867 		{
   5868 			return error(GL_INVALID_VALUE);
   5869 		}
   5870 
   5871 		es2::Program *program = context->getCurrentProgram();
   5872 
   5873 		if(!program)
   5874 		{
   5875 			return error(GL_INVALID_OPERATION);
   5876 		}
   5877 
   5878 		if(!program->setUniformMatrix3fv(location, count, transpose, value))
   5879 		{
   5880 			return error(GL_INVALID_OPERATION);
   5881 		}
   5882 	}
   5883 }
   5884 
   5885 void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
   5886 {
   5887 	TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
   5888 	      location, count, transpose, value);
   5889 
   5890 	if(count < 0)
   5891 	{
   5892 		return error(GL_INVALID_VALUE);
   5893 	}
   5894 
   5895 	if(location == -1)
   5896 	{
   5897 		return;
   5898 	}
   5899 
   5900 	es2::Context *context = es2::getContext();
   5901 
   5902 	if(context)
   5903 	{
   5904 		if(context->getClientVersion() < 3 && transpose != GL_FALSE)
   5905 		{
   5906 			return error(GL_INVALID_VALUE);
   5907 		}
   5908 
   5909 		es2::Program *program = context->getCurrentProgram();
   5910 
   5911 		if(!program)
   5912 		{
   5913 			return error(GL_INVALID_OPERATION);
   5914 		}
   5915 
   5916 		if(!program->setUniformMatrix4fv(location, count, transpose, value))
   5917 		{
   5918 			return error(GL_INVALID_OPERATION);
   5919 		}
   5920 	}
   5921 }
   5922 
   5923 void UseProgram(GLuint program)
   5924 {
   5925 	TRACE("(GLuint program = %d)", program);
   5926 
   5927 	es2::Context *context = es2::getContext();
   5928 
   5929 	if(context)
   5930 	{
   5931 		es2::Program *programObject = context->getProgram(program);
   5932 
   5933 		if(!programObject && program != 0)
   5934 		{
   5935 			if(context->getShader(program))
   5936 			{
   5937 				return error(GL_INVALID_OPERATION);
   5938 			}
   5939 			else
   5940 			{
   5941 				return error(GL_INVALID_VALUE);
   5942 			}
   5943 		}
   5944 
   5945 		if(program != 0 && !programObject->isLinked())
   5946 		{
   5947 			return error(GL_INVALID_OPERATION);
   5948 		}
   5949 
   5950 		context->useProgram(program);
   5951 	}
   5952 }
   5953 
   5954 void ValidateProgram(GLuint program)
   5955 {
   5956 	TRACE("(GLuint program = %d)", program);
   5957 
   5958 	es2::Context *context = es2::getContext();
   5959 
   5960 	if(context)
   5961 	{
   5962 		es2::Program *programObject = context->getProgram(program);
   5963 
   5964 		if(!programObject)
   5965 		{
   5966 			if(context->getShader(program))
   5967 			{
   5968 				return error(GL_INVALID_OPERATION);
   5969 			}
   5970 			else
   5971 			{
   5972 				return error(GL_INVALID_VALUE);
   5973 			}
   5974 		}
   5975 
   5976 		programObject->validate(context->getDevice());
   5977 	}
   5978 }
   5979 
   5980 void VertexAttrib1f(GLuint index, GLfloat x)
   5981 {
   5982 	TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
   5983 
   5984 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   5985 	{
   5986 		return error(GL_INVALID_VALUE);
   5987 	}
   5988 
   5989 	es2::Context *context = es2::getContext();
   5990 
   5991 	if(context)
   5992 	{
   5993 		GLfloat vals[4] = { x, 0, 0, 1 };
   5994 		context->setVertexAttrib(index, vals);
   5995 	}
   5996 }
   5997 
   5998 void VertexAttrib1fv(GLuint index, const GLfloat* values)
   5999 {
   6000 	TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
   6001 
   6002 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6003 	{
   6004 		return error(GL_INVALID_VALUE);
   6005 	}
   6006 
   6007 	es2::Context *context = es2::getContext();
   6008 
   6009 	if(context)
   6010 	{
   6011 		GLfloat vals[4] = { values[0], 0, 0, 1 };
   6012 		context->setVertexAttrib(index, vals);
   6013 	}
   6014 }
   6015 
   6016 void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
   6017 {
   6018 	TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
   6019 
   6020 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6021 	{
   6022 		return error(GL_INVALID_VALUE);
   6023 	}
   6024 
   6025 	es2::Context *context = es2::getContext();
   6026 
   6027 	if(context)
   6028 	{
   6029 		GLfloat vals[4] = { x, y, 0, 1 };
   6030 		context->setVertexAttrib(index, vals);
   6031 	}
   6032 }
   6033 
   6034 void VertexAttrib2fv(GLuint index, const GLfloat* values)
   6035 {
   6036 	TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
   6037 
   6038 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6039 	{
   6040 		return error(GL_INVALID_VALUE);
   6041 	}
   6042 
   6043 	es2::Context *context = es2::getContext();
   6044 
   6045 	if(context)
   6046 	{
   6047 		GLfloat vals[4] = { values[0], values[1], 0, 1 };
   6048 		context->setVertexAttrib(index, vals);
   6049 	}
   6050 }
   6051 
   6052 void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
   6053 {
   6054 	TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
   6055 
   6056 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6057 	{
   6058 		return error(GL_INVALID_VALUE);
   6059 	}
   6060 
   6061 	es2::Context *context = es2::getContext();
   6062 
   6063 	if(context)
   6064 	{
   6065 		GLfloat vals[4] = { x, y, z, 1 };
   6066 		context->setVertexAttrib(index, vals);
   6067 	}
   6068 }
   6069 
   6070 void VertexAttrib3fv(GLuint index, const GLfloat* values)
   6071 {
   6072 	TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
   6073 
   6074 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6075 	{
   6076 		return error(GL_INVALID_VALUE);
   6077 	}
   6078 
   6079 	es2::Context *context = es2::getContext();
   6080 
   6081 	if(context)
   6082 	{
   6083 		GLfloat vals[4] = { values[0], values[1], values[2], 1 };
   6084 		context->setVertexAttrib(index, vals);
   6085 	}
   6086 }
   6087 
   6088 void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   6089 {
   6090 	TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
   6091 
   6092 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6093 	{
   6094 		return error(GL_INVALID_VALUE);
   6095 	}
   6096 
   6097 	es2::Context *context = es2::getContext();
   6098 
   6099 	if(context)
   6100 	{
   6101 		GLfloat vals[4] = { x, y, z, w };
   6102 		context->setVertexAttrib(index, vals);
   6103 	}
   6104 }
   6105 
   6106 void VertexAttrib4fv(GLuint index, const GLfloat* values)
   6107 {
   6108 	TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
   6109 
   6110 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6111 	{
   6112 		return error(GL_INVALID_VALUE);
   6113 	}
   6114 
   6115 	es2::Context *context = es2::getContext();
   6116 
   6117 	if(context)
   6118 	{
   6119 		context->setVertexAttrib(index, values);
   6120 	}
   6121 }
   6122 
   6123 void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
   6124 {
   6125 	TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
   6126 	      "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
   6127 	      index, size, type, normalized, stride, ptr);
   6128 
   6129 	if(index >= es2::MAX_VERTEX_ATTRIBS)
   6130 	{
   6131 		return error(GL_INVALID_VALUE);
   6132 	}
   6133 
   6134 	if(size < 1 || size > 4)
   6135 	{
   6136 		return error(GL_INVALID_VALUE);
   6137 	}
   6138 
   6139 	GLint clientVersion = egl::getClientVersion();
   6140 
   6141 	switch(type)
   6142 	{
   6143 	case GL_BYTE:
   6144 	case GL_UNSIGNED_BYTE:
   6145 	case GL_SHORT:
   6146 	case GL_UNSIGNED_SHORT:
   6147 	case GL_FIXED:
   6148 	case GL_FLOAT:
   6149 	case GL_HALF_FLOAT_OES:   // GL_OES_vertex_half_float
   6150 		break;
   6151 	case GL_INT_2_10_10_10_REV:
   6152 	case GL_UNSIGNED_INT_2_10_10_10_REV:
   6153 		if(clientVersion >= 3)
   6154 		{
   6155 			if(size != 4)
   6156 			{
   6157 				return error(GL_INVALID_OPERATION);
   6158 			}
   6159 			break;
   6160 		}
   6161 		else return error(GL_INVALID_ENUM);
   6162 	case GL_INT:
   6163 	case GL_UNSIGNED_INT:
   6164 	case GL_HALF_FLOAT:
   6165 		if(clientVersion >= 3)
   6166 		{
   6167 			break;
   6168 		}
   6169 		else return error(GL_INVALID_ENUM);
   6170 	default:
   6171 		return error(GL_INVALID_ENUM);
   6172 	}
   6173 
   6174 	if(stride < 0)
   6175 	{
   6176 		return error(GL_INVALID_VALUE);
   6177 	}
   6178 
   6179 	es2::Context *context = es2::getContext();
   6180 
   6181 	if(context)
   6182 	{
   6183 		context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
   6184 	}
   6185 }
   6186 
   6187 void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
   6188 {
   6189 	TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
   6190 
   6191 	if(width < 0 || height < 0)
   6192 	{
   6193 		return error(GL_INVALID_VALUE);
   6194 	}
   6195 
   6196 	es2::Context *context = es2::getContext();
   6197 
   6198 	if(context)
   6199 	{
   6200 		context->setViewportParams(x, y, width, height);
   6201 	}
   6202 }
   6203 
   6204 static void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, bool allowPartialDepthStencilBlit)
   6205 {
   6206 	TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
   6207 	      "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
   6208 	      "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
   6209 	      srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
   6210 
   6211 	switch(filter)
   6212 	{
   6213 	case GL_NEAREST:
   6214 		break;
   6215 	default:
   6216 		return error(GL_INVALID_ENUM);
   6217 	}
   6218 
   6219 	if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
   6220 	{
   6221 		return error(GL_INVALID_VALUE);
   6222 	}
   6223 
   6224 	es2::Context *context = es2::getContext();
   6225 
   6226 	if(context)
   6227 	{
   6228 		if(context->getReadFramebufferName() == context->getDrawFramebufferName())
   6229 		{
   6230 			ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
   6231 			return error(GL_INVALID_OPERATION);
   6232 		}
   6233 
   6234 		context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
   6235 	}
   6236 }
   6237 
   6238 void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
   6239 {
   6240 	BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
   6241 }
   6242 
   6243 void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
   6244                           GLbitfield mask, GLenum filter)
   6245 {
   6246 	if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
   6247 	{
   6248 		ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
   6249 		return error(GL_INVALID_OPERATION);
   6250 	}
   6251 
   6252 	BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
   6253 }
   6254 
   6255 void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
   6256                    GLint border, GLenum format, GLenum type, const GLvoid* data)
   6257 {
   6258 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
   6259 	      "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
   6260 	      "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
   6261 	      target, level, internalformat, width, height, depth, border, format, type, data);
   6262 
   6263 	switch(target)
   6264 	{
   6265 	case GL_TEXTURE_3D_OES:
   6266 		switch(format)
   6267 		{
   6268 		case GL_DEPTH_COMPONENT:
   6269 		case GL_DEPTH_STENCIL_OES:
   6270 			return error(GL_INVALID_OPERATION);
   6271 		default:
   6272 			break;
   6273 		}
   6274 		break;
   6275 	default:
   6276 		return error(GL_INVALID_ENUM);
   6277 	}
   6278 
   6279 	if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
   6280 	{
   6281 		return;
   6282 	}
   6283 
   6284 	if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
   6285 	{
   6286 		return error(GL_INVALID_VALUE);
   6287 	}
   6288 
   6289 	const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
   6290 	if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
   6291 	{
   6292 		return error(GL_INVALID_VALUE);
   6293 	}
   6294 
   6295 	if(border != 0)
   6296 	{
   6297 		return error(GL_INVALID_VALUE);
   6298 	}
   6299 
   6300 	es2::Context *context = es2::getContext();
   6301 
   6302 	if(context)
   6303 	{
   6304 		es2::Texture3D *texture = context->getTexture3D();
   6305 
   6306 		if(!texture)
   6307 		{
   6308 			return error(GL_INVALID_OPERATION);
   6309 		}
   6310 
   6311 		texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), context->getPixels(data));
   6312 	}
   6313 }
   6314 
   6315 void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data)
   6316 {
   6317 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
   6318 	      "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
   6319 	      "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
   6320 	      target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
   6321 
   6322 	switch(target)
   6323 	{
   6324 	case GL_TEXTURE_3D_OES:
   6325 		break;
   6326 	default:
   6327 		return error(GL_INVALID_ENUM);
   6328 	}
   6329 
   6330 	if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
   6331 	{
   6332 		return;
   6333 	}
   6334 
   6335 	if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
   6336 	{
   6337 		return error(GL_INVALID_VALUE);
   6338 	}
   6339 
   6340 	if((width < 0) || (height < 0) || (depth < 0))
   6341 	{
   6342 		return error(GL_INVALID_VALUE);
   6343 	}
   6344 
   6345 	es2::Context *context = es2::getContext();
   6346 
   6347 	if(context)
   6348 	{
   6349 		es2::Texture3D *texture = context->getTexture3D();
   6350 
   6351 		GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
   6352 
   6353 		GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
   6354 		if(validationError == GL_NONE)
   6355 		{
   6356 			texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), context->getPixels(data));
   6357 		}
   6358 		else
   6359 		{
   6360 			return error(validationError);
   6361 		}
   6362 	}
   6363 }
   6364 
   6365 void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
   6366 {
   6367 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
   6368 	      "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
   6369 	      target, level, xoffset, yoffset, zoffset, x, y, width, height);
   6370 
   6371 	switch(target)
   6372 	{
   6373 	case GL_TEXTURE_3D_OES:
   6374 		break;
   6375 	default:
   6376 		return error(GL_INVALID_ENUM);
   6377 	}
   6378 
   6379 	if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
   6380 	{
   6381 		return error(GL_INVALID_VALUE);
   6382 	}
   6383 
   6384 	es2::Context *context = es2::getContext();
   6385 
   6386 	if(context)
   6387 	{
   6388 		es2::Framebuffer *framebuffer = context->getReadFramebuffer();
   6389 
   6390 		if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
   6391 		{
   6392 			return error(GL_INVALID_FRAMEBUFFER_OPERATION);
   6393 		}
   6394 
   6395 		es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
   6396 
   6397 		if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
   6398 		{
   6399 			return error(GL_INVALID_OPERATION);
   6400 		}
   6401 
   6402 		es2::Texture3D *texture = context->getTexture3D();
   6403 
   6404 		GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
   6405 
   6406 		if(validationError != GL_NONE)
   6407 		{
   6408 			return error(validationError);
   6409 		}
   6410 
   6411 		texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
   6412 	}
   6413 }
   6414 
   6415 void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
   6416 {
   6417 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
   6418 	      "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
   6419 	      target, level, internalformat, width, height, depth, border, imageSize, data);
   6420 
   6421 	switch(target)
   6422 	{
   6423 	case GL_TEXTURE_3D_OES:
   6424 		break;
   6425 	default:
   6426 		return error(GL_INVALID_ENUM);
   6427 	}
   6428 
   6429 	if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
   6430 	{
   6431 		return error(GL_INVALID_VALUE);
   6432 	}
   6433 
   6434 	const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
   6435 	if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
   6436 	{
   6437 		return error(GL_INVALID_VALUE);
   6438 	}
   6439 
   6440 	switch(internalformat)
   6441 	{
   6442 	case GL_DEPTH_COMPONENT:
   6443 	case GL_DEPTH_COMPONENT16:
   6444 	case GL_DEPTH_COMPONENT32_OES:
   6445 	case GL_DEPTH_STENCIL_OES:
   6446 	case GL_DEPTH24_STENCIL8_OES:
   6447 		return error(GL_INVALID_OPERATION);
   6448 	default:
   6449 		{
   6450 			GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
   6451 			if(validationError != GL_NONE)
   6452 			{
   6453 				return error(validationError);
   6454 			}
   6455 		}
   6456 	}
   6457 
   6458 	if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
   6459 	{
   6460 		return error(GL_INVALID_VALUE);
   6461 	}
   6462 
   6463 	es2::Context *context = es2::getContext();
   6464 
   6465 	if(context)
   6466 	{
   6467 		es2::Texture3D *texture = context->getTexture3D();
   6468 
   6469 		if(!texture)
   6470 		{
   6471 			return error(GL_INVALID_OPERATION);
   6472 		}
   6473 
   6474 		texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
   6475 	}
   6476 }
   6477 
   6478 void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
   6479 {
   6480 	TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
   6481 	      "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
   6482 	      "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
   6483 	      target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
   6484 
   6485 	switch(target)
   6486 	{
   6487 	case GL_TEXTURE_3D_OES:
   6488 		break;
   6489 	default:
   6490 		return error(GL_INVALID_ENUM);
   6491 	}
   6492 
   6493 	if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   6494 	{
   6495 		return error(GL_INVALID_VALUE);
   6496 	}
   6497 
   6498 	if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
   6499 	{
   6500 		return error(GL_INVALID_VALUE);
   6501 	}
   6502 
   6503 	GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
   6504 	if(validationError != GL_NONE)
   6505 	{
   6506 		return error(validationError);
   6507 	}
   6508 
   6509 	if(width == 0 || height == 0 || depth == 0 || !data)
   6510 	{
   6511 		return;
   6512 	}
   6513 
   6514 	es2::Context *context = es2::getContext();
   6515 
   6516 	if(context)
   6517 	{
   6518 		es2::Texture3D *texture = context->getTexture3D();
   6519 
   6520 		if(!texture)
   6521 		{
   6522 			return error(GL_INVALID_OPERATION);
   6523 		}
   6524 
   6525 		texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, context->getPixels(data));
   6526 	}
   6527 }
   6528 
   6529 void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
   6530 {
   6531 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
   6532 	      "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
   6533 
   6534 	if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
   6535 	{
   6536 		return error(GL_INVALID_ENUM);
   6537 	}
   6538 
   6539 	es2::Context *context = es2::getContext();
   6540 
   6541 	if(context)
   6542 	{
   6543 		if(texture == 0)
   6544 		{
   6545 			textarget = GL_NONE;
   6546 		}
   6547 		else
   6548 		{
   6549 			es2::Texture *tex = context->getTexture(texture);
   6550 
   6551 			if(!tex)
   6552 			{
   6553 				return error(GL_INVALID_OPERATION);
   6554 			}
   6555 
   6556 			if(tex->isCompressed(textarget, level))
   6557 			{
   6558 				return error(GL_INVALID_OPERATION);
   6559 			}
   6560 
   6561 			switch(textarget)
   6562 			{
   6563 			case GL_TEXTURE_3D_OES:
   6564 				if(tex->getTarget() != GL_TEXTURE_3D_OES)
   6565 				{
   6566 					return error(GL_INVALID_OPERATION);
   6567 				}
   6568 				break;
   6569 			default:
   6570 				return error(GL_INVALID_ENUM);
   6571 			}
   6572 
   6573 			if(level != 0)
   6574 			{
   6575 				return error(GL_INVALID_VALUE);
   6576 			}
   6577 		}
   6578 
   6579 		es2::Framebuffer *framebuffer = nullptr;
   6580 		GLuint framebufferName = 0;
   6581 		if(target == GL_READ_FRAMEBUFFER_ANGLE)
   6582 		{
   6583 			framebuffer = context->getReadFramebuffer();
   6584 			framebufferName = context->getReadFramebufferName();
   6585 		}
   6586 		else
   6587 		{
   6588 			framebuffer = context->getDrawFramebuffer();
   6589 			framebufferName = context->getDrawFramebufferName();
   6590 		}
   6591 
   6592 		if(framebufferName == 0 || !framebuffer)
   6593 		{
   6594 			return error(GL_INVALID_OPERATION);
   6595 		}
   6596 
   6597 		GLint clientVersion = context->getClientVersion();
   6598 
   6599 		switch(attachment)
   6600 		{
   6601 		case GL_COLOR_ATTACHMENT1:
   6602 		case GL_COLOR_ATTACHMENT2:
   6603 		case GL_COLOR_ATTACHMENT3:
   6604 		case GL_COLOR_ATTACHMENT4:
   6605 		case GL_COLOR_ATTACHMENT5:
   6606 		case GL_COLOR_ATTACHMENT6:
   6607 		case GL_COLOR_ATTACHMENT7:
   6608 		case GL_COLOR_ATTACHMENT8:
   6609 		case GL_COLOR_ATTACHMENT9:
   6610 		case GL_COLOR_ATTACHMENT10:
   6611 		case GL_COLOR_ATTACHMENT11:
   6612 		case GL_COLOR_ATTACHMENT12:
   6613 		case GL_COLOR_ATTACHMENT13:
   6614 		case GL_COLOR_ATTACHMENT14:
   6615 		case GL_COLOR_ATTACHMENT15:
   6616 		case GL_COLOR_ATTACHMENT16:
   6617 		case GL_COLOR_ATTACHMENT17:
   6618 		case GL_COLOR_ATTACHMENT18:
   6619 		case GL_COLOR_ATTACHMENT19:
   6620 		case GL_COLOR_ATTACHMENT20:
   6621 		case GL_COLOR_ATTACHMENT21:
   6622 		case GL_COLOR_ATTACHMENT22:
   6623 		case GL_COLOR_ATTACHMENT23:
   6624 		case GL_COLOR_ATTACHMENT24:
   6625 		case GL_COLOR_ATTACHMENT25:
   6626 		case GL_COLOR_ATTACHMENT26:
   6627 		case GL_COLOR_ATTACHMENT27:
   6628 		case GL_COLOR_ATTACHMENT28:
   6629 		case GL_COLOR_ATTACHMENT29:
   6630 		case GL_COLOR_ATTACHMENT30:
   6631 		case GL_COLOR_ATTACHMENT31:
   6632 			if(clientVersion < 3)
   6633 			{
   6634 				return error(GL_INVALID_ENUM);
   6635 			}
   6636 			// fall through
   6637 		case GL_COLOR_ATTACHMENT0:
   6638 			if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
   6639 			{
   6640 				return error(GL_INVALID_ENUM);
   6641 			}
   6642 			framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
   6643 			break;
   6644 		case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;
   6645 		case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
   6646 		default:
   6647 			return error(GL_INVALID_ENUM);
   6648 		}
   6649 	}
   6650 }
   6651 
   6652 void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
   6653 {
   6654 	if(egl::getClientVersion() == 1)
   6655 	{
   6656 		return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
   6657 	}
   6658 
   6659 	TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
   6660 
   6661 	switch(target)
   6662 	{
   6663 	case GL_TEXTURE_2D:
   6664 	case GL_TEXTURE_EXTERNAL_OES:
   6665 		break;
   6666 	default:
   6667 		return error(GL_INVALID_ENUM);
   6668 	}
   6669 
   6670 	es2::Context *context = es2::getContext();
   6671 
   6672 	if(context)
   6673 	{
   6674 		es2::Texture2D *texture = nullptr;
   6675 
   6676 		switch(target)
   6677 		{
   6678 		case GL_TEXTURE_2D:           texture = context->getTexture2D();       break;
   6679 		case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
   6680 		default:                      UNREACHABLE(target);
   6681 		}
   6682 
   6683 		if(!texture)
   6684 		{
   6685 			return error(GL_INVALID_OPERATION);
   6686 		}
   6687 
   6688 		egl::Image *eglImage = context->getSharedImage(image);
   6689 
   6690 		if(!eglImage)
   6691 		{
   6692 			return error(GL_INVALID_OPERATION);
   6693 		}
   6694 
   6695 		texture->setSharedImage(eglImage);
   6696 	}
   6697 }
   6698 
   6699 void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
   6700 {
   6701 	TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
   6702 
   6703 	UNIMPLEMENTED();
   6704 }
   6705 
   6706 GLboolean IsRenderbufferOES(GLuint renderbuffer)
   6707 {
   6708 	return IsRenderbuffer(renderbuffer);
   6709 }
   6710 
   6711 void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
   6712 {
   6713 	BindRenderbuffer(target, renderbuffer);
   6714 }
   6715 
   6716 void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
   6717 {
   6718 	DeleteRenderbuffers(n, renderbuffers);
   6719 }
   6720 
   6721 void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
   6722 {
   6723 	GenRenderbuffers(n, renderbuffers);
   6724 }
   6725 
   6726 void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
   6727 {
   6728 	RenderbufferStorage(target, internalformat, width, height);
   6729 }
   6730 
   6731 void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
   6732 {
   6733 	GetRenderbufferParameteriv(target, pname, params);
   6734 }
   6735 
   6736 GLboolean IsFramebufferOES(GLuint framebuffer)
   6737 {
   6738 	return IsFramebuffer(framebuffer);
   6739 }
   6740 
   6741 void BindFramebufferOES(GLenum target, GLuint framebuffer)
   6742 {
   6743 	BindFramebuffer(target, framebuffer);
   6744 }
   6745 
   6746 void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
   6747 {
   6748 	DeleteFramebuffers(n, framebuffers);
   6749 }
   6750 
   6751 void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
   6752 {
   6753 	GenFramebuffers(n, framebuffers);
   6754 }
   6755 
   6756 GLenum CheckFramebufferStatusOES(GLenum target)
   6757 {
   6758 	return CheckFramebufferStatus(target);
   6759 }
   6760 
   6761 void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
   6762 {
   6763 	FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
   6764 }
   6765 
   6766 void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
   6767 {
   6768 	FramebufferTexture2D(target, attachment, textarget, texture, level);
   6769 }
   6770 
   6771 void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
   6772 {
   6773 	GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
   6774 }
   6775 
   6776 void GenerateMipmapOES(GLenum target)
   6777 {
   6778 	GenerateMipmap(target);
   6779 }
   6780 
   6781 void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
   6782 {
   6783 	TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
   6784 
   6785 	if(n < 0 || n > MAX_DRAW_BUFFERS)
   6786 	{
   6787 		return error(GL_INVALID_VALUE);
   6788 	}
   6789 
   6790 	es2::Context *context = es2::getContext();
   6791 
   6792 	if(context)
   6793 	{
   6794 		GLuint drawFramebufferName = context->getDrawFramebufferName();
   6795 
   6796 		if((drawFramebufferName == 0) && (n != 1))
   6797 		{
   6798 			return error(GL_INVALID_OPERATION);
   6799 		}
   6800 
   6801 		for(unsigned int i = 0; i < (unsigned)n; i++)
   6802 		{
   6803 			switch(bufs[i])
   6804 			{
   6805 			case GL_BACK:
   6806 				if(drawFramebufferName != 0)
   6807 				{
   6808 					return error(GL_INVALID_OPERATION);
   6809 				}
   6810 				break;
   6811 			case GL_NONE:
   6812 				break;
   6813 			case GL_COLOR_ATTACHMENT0_EXT:
   6814 			case GL_COLOR_ATTACHMENT1_EXT:
   6815 			case GL_COLOR_ATTACHMENT2_EXT:
   6816 			case GL_COLOR_ATTACHMENT3_EXT:
   6817 			case GL_COLOR_ATTACHMENT4_EXT:
   6818 			case GL_COLOR_ATTACHMENT5_EXT:
   6819 			case GL_COLOR_ATTACHMENT6_EXT:
   6820 			case GL_COLOR_ATTACHMENT7_EXT:
   6821 			case GL_COLOR_ATTACHMENT8_EXT:
   6822 			case GL_COLOR_ATTACHMENT9_EXT:
   6823 			case GL_COLOR_ATTACHMENT10_EXT:
   6824 			case GL_COLOR_ATTACHMENT11_EXT:
   6825 			case GL_COLOR_ATTACHMENT12_EXT:
   6826 			case GL_COLOR_ATTACHMENT13_EXT:
   6827 			case GL_COLOR_ATTACHMENT14_EXT:
   6828 			case GL_COLOR_ATTACHMENT15_EXT:
   6829 				{
   6830 					GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
   6831 
   6832 					if(index >= MAX_COLOR_ATTACHMENTS)
   6833 					{
   6834 						return error(GL_INVALID_OPERATION);
   6835 					}
   6836 
   6837 					if(index != i)
   6838 					{
   6839 						return error(GL_INVALID_OPERATION);
   6840 					}
   6841 
   6842 					if(drawFramebufferName == 0)
   6843 					{
   6844 						return error(GL_INVALID_OPERATION);
   6845 					}
   6846 				}
   6847 				break;
   6848 			default:
   6849 				return error(GL_INVALID_ENUM);
   6850 			}
   6851 		}
   6852 
   6853 		context->setFramebufferDrawBuffers(n, bufs);
   6854 	}
   6855 }
   6856 
   6857 }
   6858 
   6859 extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
   6860 {
   6861 	struct Extension
   6862 	{
   6863 		const char *name;
   6864 		__eglMustCastToProperFunctionPointerType address;
   6865 	};
   6866 
   6867 	static const Extension glExtensions[] =
   6868 	{
   6869 		#define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
   6870 
   6871 		EXTENSION(glTexImage3DOES),
   6872 		EXTENSION(glBlitFramebufferANGLE),
   6873 		EXTENSION(glBlitFramebufferNV),
   6874 		EXTENSION(glRenderbufferStorageMultisampleANGLE),
   6875 		EXTENSION(glDeleteFencesNV),
   6876 		EXTENSION(glGenFencesNV),
   6877 		EXTENSION(glIsFenceNV),
   6878 		EXTENSION(glTestFenceNV),
   6879 		EXTENSION(glGetFenceivNV),
   6880 		EXTENSION(glFinishFenceNV),
   6881 		EXTENSION(glSetFenceNV),
   6882 		EXTENSION(glGetGraphicsResetStatusEXT),
   6883 		EXTENSION(glReadnPixelsEXT),
   6884 		EXTENSION(glGetnUniformfvEXT),
   6885 		EXTENSION(glGetnUniformivEXT),
   6886 		EXTENSION(glGenQueriesEXT),
   6887 		EXTENSION(glDeleteQueriesEXT),
   6888 		EXTENSION(glIsQueryEXT),
   6889 		EXTENSION(glBeginQueryEXT),
   6890 		EXTENSION(glEndQueryEXT),
   6891 		EXTENSION(glGetQueryivEXT),
   6892 		EXTENSION(glGetQueryObjectuivEXT),
   6893 		EXTENSION(glEGLImageTargetTexture2DOES),
   6894 		EXTENSION(glEGLImageTargetRenderbufferStorageOES),
   6895 		EXTENSION(glDrawElementsInstancedEXT),
   6896 		EXTENSION(glDrawArraysInstancedEXT),
   6897 		EXTENSION(glVertexAttribDivisorEXT),
   6898 		EXTENSION(glDrawArraysInstancedANGLE),
   6899 		EXTENSION(glDrawElementsInstancedANGLE),
   6900 		EXTENSION(glVertexAttribDivisorANGLE),
   6901 		EXTENSION(glIsRenderbufferOES),
   6902 		EXTENSION(glBindRenderbufferOES),
   6903 		EXTENSION(glDeleteRenderbuffersOES),
   6904 		EXTENSION(glGenRenderbuffersOES),
   6905 		EXTENSION(glRenderbufferStorageOES),
   6906 		EXTENSION(glGetRenderbufferParameterivOES),
   6907 		EXTENSION(glIsFramebufferOES),
   6908 		EXTENSION(glBindFramebufferOES),
   6909 		EXTENSION(glDeleteFramebuffersOES),
   6910 		EXTENSION(glGenFramebuffersOES),
   6911 		EXTENSION(glCheckFramebufferStatusOES),
   6912 		EXTENSION(glFramebufferRenderbufferOES),
   6913 		EXTENSION(glFramebufferTexture2DOES),
   6914 		EXTENSION(glGetFramebufferAttachmentParameterivOES),
   6915 		EXTENSION(glGenerateMipmapOES),
   6916 		EXTENSION(glDrawBuffersEXT),
   6917 
   6918 		#undef EXTENSION
   6919 	};
   6920 
   6921 	for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
   6922 	{
   6923 		if(strcmp(procname, glExtensions[ext].name) == 0)
   6924 		{
   6925 			return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
   6926 		}
   6927 	}
   6928 
   6929 	return nullptr;
   6930 }
   6931