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