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