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