OSDN Git Service

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