1#include "precompiled.h"
2//
3// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
9
10#include "common/version.h"
11
12#include "libGLESv2/main.h"
13#include "common/utilities.h"
14#include "libGLESv2/formatutils.h"
15#include "libGLESv2/Buffer.h"
16#include "libGLESv2/Fence.h"
17#include "libGLESv2/Framebuffer.h"
18#include "libGLESv2/Renderbuffer.h"
19#include "libGLESv2/Program.h"
20#include "libGLESv2/ProgramBinary.h"
21#include "libGLESv2/Texture.h"
22#include "libGLESv2/Query.h"
23#include "libGLESv2/Context.h"
24#include "libGLESv2/VertexArray.h"
25#include "libGLESv2/TransformFeedback.h"
26
27#include "libGLESv2/validationES.h"
28#include "libGLESv2/validationES2.h"
29#include "libGLESv2/validationES3.h"
30#include "libGLESv2/queryconversions.h"
31
32extern "C"
33{
34
35// OpenGL ES 2.0 functions
36
37void __stdcall glActiveTexture(GLenum texture)
38{
39    EVENT("(GLenum texture = 0x%X)", texture);
40
41    try
42    {
43        gl::Context *context = gl::getNonLostContext();
44
45        if (context)
46        {
47            if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1)
48            {
49                return gl::error(GL_INVALID_ENUM);
50            }
51
52            context->setActiveSampler(texture - GL_TEXTURE0);
53        }
54    }
55    catch (...)
56    {
57        return gl::error(GL_OUT_OF_MEMORY);
58    }
59}
60
61void __stdcall glAttachShader(GLuint program, GLuint shader)
62{
63    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
64
65    try
66    {
67        gl::Context *context = gl::getNonLostContext();
68
69        if (context)
70        {
71            gl::Program *programObject = context->getProgram(program);
72            gl::Shader *shaderObject = context->getShader(shader);
73
74            if (!programObject)
75            {
76                if (context->getShader(program))
77                {
78                    return gl::error(GL_INVALID_OPERATION);
79                }
80                else
81                {
82                    return gl::error(GL_INVALID_VALUE);
83                }
84            }
85
86            if (!shaderObject)
87            {
88                if (context->getProgram(shader))
89                {
90                    return gl::error(GL_INVALID_OPERATION);
91                }
92                else
93                {
94                    return gl::error(GL_INVALID_VALUE);
95                }
96            }
97
98            if (!programObject->attachShader(shaderObject))
99            {
100                return gl::error(GL_INVALID_OPERATION);
101            }
102        }
103    }
104    catch (...)
105    {
106        return gl::error(GL_OUT_OF_MEMORY);
107    }
108}
109
110void __stdcall glBeginQueryEXT(GLenum target, GLuint id)
111{
112    EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
113
114    try
115    {
116        gl::Context *context = gl::getNonLostContext();
117
118        if (context)
119        {
120            if (!ValidateBeginQuery(context, target, id))
121            {
122                return;
123            }
124
125            context->beginQuery(target, id);
126        }
127    }
128    catch (...)
129    {
130        return gl::error(GL_OUT_OF_MEMORY);
131    }
132}
133
134void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
135{
136    EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
137
138    try
139    {
140        if (index >= gl::MAX_VERTEX_ATTRIBS)
141        {
142            return gl::error(GL_INVALID_VALUE);
143        }
144
145        gl::Context *context = gl::getNonLostContext();
146
147        if (context)
148        {
149            gl::Program *programObject = context->getProgram(program);
150
151            if (!programObject)
152            {
153                if (context->getShader(program))
154                {
155                    return gl::error(GL_INVALID_OPERATION);
156                }
157                else
158                {
159                    return gl::error(GL_INVALID_VALUE);
160                }
161            }
162
163            if (strncmp(name, "gl_", 3) == 0)
164            {
165                return gl::error(GL_INVALID_OPERATION);
166            }
167
168            programObject->bindAttributeLocation(index, name);
169        }
170    }
171    catch (...)
172    {
173        return gl::error(GL_OUT_OF_MEMORY);
174    }
175}
176
177void __stdcall glBindBuffer(GLenum target, GLuint buffer)
178{
179    EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
180
181    try
182    {
183        gl::Context *context = gl::getNonLostContext();
184
185        if (context)
186        {
187            if (!gl::ValidBufferTarget(context, target))
188            {
189                return gl::error(GL_INVALID_ENUM);
190            }
191
192            switch (target)
193            {
194              case GL_ARRAY_BUFFER:
195                context->bindArrayBuffer(buffer);
196                return;
197              case GL_ELEMENT_ARRAY_BUFFER:
198                context->bindElementArrayBuffer(buffer);
199                return;
200              case GL_COPY_READ_BUFFER:
201                context->bindCopyReadBuffer(buffer);
202                return;
203              case GL_COPY_WRITE_BUFFER:
204                context->bindCopyWriteBuffer(buffer);
205                return;
206              case GL_PIXEL_PACK_BUFFER:
207                context->bindPixelPackBuffer(buffer);
208                return;
209              case GL_PIXEL_UNPACK_BUFFER:
210                context->bindPixelUnpackBuffer(buffer);
211                return;
212              case GL_UNIFORM_BUFFER:
213                context->bindGenericUniformBuffer(buffer);
214                return;
215              case GL_TRANSFORM_FEEDBACK_BUFFER:
216                context->bindGenericTransformFeedbackBuffer(buffer);
217                return;
218              default:
219                return gl::error(GL_INVALID_ENUM);
220            }
221        }
222    }
223    catch (...)
224    {
225        return gl::error(GL_OUT_OF_MEMORY);
226    }
227}
228
229void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer)
230{
231    EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
232
233    try
234    {
235        if (!gl::ValidFramebufferTarget(target))
236        {
237            return gl::error(GL_INVALID_ENUM);
238        }
239
240        gl::Context *context = gl::getNonLostContext();
241
242        if (context)
243        {
244            if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
245            {
246                context->bindReadFramebuffer(framebuffer);
247            }
248
249            if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
250            {
251                context->bindDrawFramebuffer(framebuffer);
252            }
253        }
254    }
255    catch (...)
256    {
257        return gl::error(GL_OUT_OF_MEMORY);
258    }
259}
260
261void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer)
262{
263    EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
264
265    try
266    {
267        if (target != GL_RENDERBUFFER)
268        {
269            return gl::error(GL_INVALID_ENUM);
270        }
271
272        gl::Context *context = gl::getNonLostContext();
273
274        if (context)
275        {
276            context->bindRenderbuffer(renderbuffer);
277        }
278    }
279    catch (...)
280    {
281        return gl::error(GL_OUT_OF_MEMORY);
282    }
283}
284
285void __stdcall glBindTexture(GLenum target, GLuint texture)
286{
287    EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
288
289    try
290    {
291        gl::Context *context = gl::getNonLostContext();
292
293        if (context)
294        {
295            gl::Texture *textureObject = context->getTexture(texture);
296
297            if (textureObject && textureObject->getTarget() != target && texture != 0)
298            {
299                return gl::error(GL_INVALID_OPERATION);
300            }
301
302            switch (target)
303            {
304              case GL_TEXTURE_2D:
305                context->bindTexture2D(texture);
306                return;
307              case GL_TEXTURE_CUBE_MAP:
308                context->bindTextureCubeMap(texture);
309                return;
310              case GL_TEXTURE_3D:
311                if (context->getClientVersion() < 3)
312                {
313                    return gl::error(GL_INVALID_ENUM);
314                }
315                context->bindTexture3D(texture);
316                return;
317              case GL_TEXTURE_2D_ARRAY:
318                if (context->getClientVersion() < 3)
319                {
320                    return gl::error(GL_INVALID_ENUM);
321                }
322                context->bindTexture2DArray(texture);
323                return;
324              default:
325                return gl::error(GL_INVALID_ENUM);
326            }
327        }
328    }
329    catch (...)
330    {
331        return gl::error(GL_OUT_OF_MEMORY);
332    }
333}
334
335void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
336{
337    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
338          red, green, blue, alpha);
339
340    try
341    {
342        gl::Context* context = gl::getNonLostContext();
343
344        if (context)
345        {
346            context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
347        }
348    }
349    catch (...)
350    {
351        return gl::error(GL_OUT_OF_MEMORY);
352    }
353}
354
355void __stdcall glBlendEquation(GLenum mode)
356{
357    glBlendEquationSeparate(mode, mode);
358}
359
360void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
361{
362    EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
363
364    try
365    {
366        gl::Context *context = gl::getNonLostContext();
367
368        switch (modeRGB)
369        {
370          case GL_FUNC_ADD:
371          case GL_FUNC_SUBTRACT:
372          case GL_FUNC_REVERSE_SUBTRACT:
373          case GL_MIN:
374          case GL_MAX:
375            break;
376
377          default:
378            return gl::error(GL_INVALID_ENUM);
379        }
380
381        switch (modeAlpha)
382        {
383          case GL_FUNC_ADD:
384          case GL_FUNC_SUBTRACT:
385          case GL_FUNC_REVERSE_SUBTRACT:
386          case GL_MIN:
387          case GL_MAX:
388            break;
389
390          default:
391            return gl::error(GL_INVALID_ENUM);
392        }
393
394        if (context)
395        {
396            context->setBlendEquation(modeRGB, modeAlpha);
397        }
398    }
399    catch (...)
400    {
401        return gl::error(GL_OUT_OF_MEMORY);
402    }
403}
404
405void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor)
406{
407    glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
408}
409
410void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
411{
412    EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
413          srcRGB, dstRGB, srcAlpha, dstAlpha);
414
415    try
416    {
417        gl::Context *context = gl::getNonLostContext();
418
419        switch (srcRGB)
420        {
421          case GL_ZERO:
422          case GL_ONE:
423          case GL_SRC_COLOR:
424          case GL_ONE_MINUS_SRC_COLOR:
425          case GL_DST_COLOR:
426          case GL_ONE_MINUS_DST_COLOR:
427          case GL_SRC_ALPHA:
428          case GL_ONE_MINUS_SRC_ALPHA:
429          case GL_DST_ALPHA:
430          case GL_ONE_MINUS_DST_ALPHA:
431          case GL_CONSTANT_COLOR:
432          case GL_ONE_MINUS_CONSTANT_COLOR:
433          case GL_CONSTANT_ALPHA:
434          case GL_ONE_MINUS_CONSTANT_ALPHA:
435          case GL_SRC_ALPHA_SATURATE:
436            break;
437          default:
438            return gl::error(GL_INVALID_ENUM);
439        }
440
441        switch (dstRGB)
442        {
443          case GL_ZERO:
444          case GL_ONE:
445          case GL_SRC_COLOR:
446          case GL_ONE_MINUS_SRC_COLOR:
447          case GL_DST_COLOR:
448          case GL_ONE_MINUS_DST_COLOR:
449          case GL_SRC_ALPHA:
450          case GL_ONE_MINUS_SRC_ALPHA:
451          case GL_DST_ALPHA:
452          case GL_ONE_MINUS_DST_ALPHA:
453          case GL_CONSTANT_COLOR:
454          case GL_ONE_MINUS_CONSTANT_COLOR:
455          case GL_CONSTANT_ALPHA:
456          case GL_ONE_MINUS_CONSTANT_ALPHA:
457            break;
458
459          case GL_SRC_ALPHA_SATURATE:
460            if (!context || context->getClientVersion() < 3)
461            {
462                return gl::error(GL_INVALID_ENUM);
463            }
464            break;
465
466          default:
467            return gl::error(GL_INVALID_ENUM);
468        }
469
470        switch (srcAlpha)
471        {
472          case GL_ZERO:
473          case GL_ONE:
474          case GL_SRC_COLOR:
475          case GL_ONE_MINUS_SRC_COLOR:
476          case GL_DST_COLOR:
477          case GL_ONE_MINUS_DST_COLOR:
478          case GL_SRC_ALPHA:
479          case GL_ONE_MINUS_SRC_ALPHA:
480          case GL_DST_ALPHA:
481          case GL_ONE_MINUS_DST_ALPHA:
482          case GL_CONSTANT_COLOR:
483          case GL_ONE_MINUS_CONSTANT_COLOR:
484          case GL_CONSTANT_ALPHA:
485          case GL_ONE_MINUS_CONSTANT_ALPHA:
486          case GL_SRC_ALPHA_SATURATE:
487            break;
488          default:
489            return gl::error(GL_INVALID_ENUM);
490        }
491
492        switch (dstAlpha)
493        {
494          case GL_ZERO:
495          case GL_ONE:
496          case GL_SRC_COLOR:
497          case GL_ONE_MINUS_SRC_COLOR:
498          case GL_DST_COLOR:
499          case GL_ONE_MINUS_DST_COLOR:
500          case GL_SRC_ALPHA:
501          case GL_ONE_MINUS_SRC_ALPHA:
502          case GL_DST_ALPHA:
503          case GL_ONE_MINUS_DST_ALPHA:
504          case GL_CONSTANT_COLOR:
505          case GL_ONE_MINUS_CONSTANT_COLOR:
506          case GL_CONSTANT_ALPHA:
507          case GL_ONE_MINUS_CONSTANT_ALPHA:
508            break;
509
510          case GL_SRC_ALPHA_SATURATE:
511            if (!context || context->getClientVersion() < 3)
512            {
513                return gl::error(GL_INVALID_ENUM);
514            }
515            break;
516
517          default:
518            return gl::error(GL_INVALID_ENUM);
519        }
520
521        bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
522                                  dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
523
524        bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
525                                  dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
526
527        if (constantColorUsed && constantAlphaUsed)
528        {
529            ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
530            return gl::error(GL_INVALID_OPERATION);
531        }
532
533        if (context)
534        {
535            context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
536        }
537    }
538    catch (...)
539    {
540        return gl::error(GL_OUT_OF_MEMORY);
541    }
542}
543
544void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
545{
546    EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
547          target, size, data, usage);
548
549    try
550    {
551        if (size < 0)
552        {
553            return gl::error(GL_INVALID_VALUE);
554        }
555
556        gl::Context *context = gl::getNonLostContext();
557
558        switch (usage)
559        {
560          case GL_STREAM_DRAW:
561          case GL_STATIC_DRAW:
562          case GL_DYNAMIC_DRAW:
563            break;
564
565          case GL_STREAM_READ:
566          case GL_STREAM_COPY:
567          case GL_STATIC_READ:
568          case GL_STATIC_COPY:
569          case GL_DYNAMIC_READ:
570          case GL_DYNAMIC_COPY:
571            if (context && context->getClientVersion() < 3)
572            {
573              return gl::error(GL_INVALID_ENUM);
574            }
575            break;
576
577          default:
578            return gl::error(GL_INVALID_ENUM);
579        }
580
581        if (context)
582        {
583            if (!gl::ValidBufferTarget(context, target))
584            {
585                return gl::error(GL_INVALID_ENUM);
586            }
587
588            gl::Buffer *buffer = context->getTargetBuffer(target);
589
590            if (!buffer)
591            {
592                return gl::error(GL_INVALID_OPERATION);
593            }
594
595            buffer->bufferData(data, size, usage);
596        }
597    }
598    catch (...)
599    {
600        return gl::error(GL_OUT_OF_MEMORY);
601    }
602}
603
604void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
605{
606    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
607          target, offset, size, data);
608
609    try
610    {
611        if (size < 0 || offset < 0)
612        {
613            return gl::error(GL_INVALID_VALUE);
614        }
615
616        if (data == NULL)
617        {
618            return;
619        }
620
621        gl::Context *context = gl::getNonLostContext();
622
623        if (context)
624        {
625            if (!gl::ValidBufferTarget(context, target))
626            {
627                return gl::error(GL_INVALID_ENUM);
628            }
629
630            gl::Buffer *buffer = context->getTargetBuffer(target);
631
632            if (!buffer)
633            {
634                return gl::error(GL_INVALID_OPERATION);
635            }
636
637            if (buffer->mapped())
638            {
639                return gl::error(GL_INVALID_OPERATION);
640            }
641
642            // Check for possible overflow of size + offset
643            if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset))
644            {
645                return gl::error(GL_OUT_OF_MEMORY);
646            }
647
648            if (size + offset > buffer->size())
649            {
650                return gl::error(GL_INVALID_VALUE);
651            }
652
653            buffer->bufferSubData(data, size, offset);
654        }
655    }
656    catch (...)
657    {
658        return gl::error(GL_OUT_OF_MEMORY);
659    }
660}
661
662GLenum __stdcall glCheckFramebufferStatus(GLenum target)
663{
664    EVENT("(GLenum target = 0x%X)", target);
665
666    try
667    {
668        if (!gl::ValidFramebufferTarget(target))
669        {
670            return gl::error(GL_INVALID_ENUM, 0);
671        }
672
673        gl::Context *context = gl::getNonLostContext();
674
675        if (context)
676        {
677            gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
678            ASSERT(framebuffer);
679            return framebuffer->completeness();
680        }
681    }
682    catch (...)
683    {
684        return gl::error(GL_OUT_OF_MEMORY, 0);
685    }
686
687    return 0;
688}
689
690void __stdcall glClear(GLbitfield mask)
691{
692    EVENT("(GLbitfield mask = 0x%X)", mask);
693
694    try
695    {
696        gl::Context *context = gl::getNonLostContext();
697
698        if (context)
699        {
700            gl::Framebuffer *framebufferObject = context->getDrawFramebuffer();
701
702            if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
703            {
704                return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
705            }
706
707            if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
708            {
709                return gl::error(GL_INVALID_VALUE);
710            }
711
712            context->clear(mask);
713        }
714    }
715    catch (...)
716    {
717        return gl::error(GL_OUT_OF_MEMORY);
718    }
719}
720
721void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
722{
723    EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
724          red, green, blue, alpha);
725
726    try
727    {
728        gl::Context *context = gl::getNonLostContext();
729
730        if (context)
731        {
732            context->setClearColor(red, green, blue, alpha);
733        }
734    }
735    catch (...)
736    {
737        return gl::error(GL_OUT_OF_MEMORY);
738    }
739}
740
741void __stdcall glClearDepthf(GLclampf depth)
742{
743    EVENT("(GLclampf depth = %f)", depth);
744
745    try
746    {
747        gl::Context *context = gl::getNonLostContext();
748
749        if (context)
750        {
751            context->setClearDepth(depth);
752        }
753    }
754    catch (...)
755    {
756        return gl::error(GL_OUT_OF_MEMORY);
757    }
758}
759
760void __stdcall glClearStencil(GLint s)
761{
762    EVENT("(GLint s = %d)", s);
763
764    try
765    {
766        gl::Context *context = gl::getNonLostContext();
767
768        if (context)
769        {
770            context->setClearStencil(s);
771        }
772    }
773    catch (...)
774    {
775        return gl::error(GL_OUT_OF_MEMORY);
776    }
777}
778
779void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
780{
781    EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
782          red, green, blue, alpha);
783
784    try
785    {
786        gl::Context *context = gl::getNonLostContext();
787
788        if (context)
789        {
790            context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
791        }
792    }
793    catch (...)
794    {
795        return gl::error(GL_OUT_OF_MEMORY);
796    }
797}
798
799void __stdcall glCompileShader(GLuint shader)
800{
801    EVENT("(GLuint shader = %d)", shader);
802
803    try
804    {
805        gl::Context *context = gl::getNonLostContext();
806
807        if (context)
808        {
809            gl::Shader *shaderObject = context->getShader(shader);
810
811            if (!shaderObject)
812            {
813                if (context->getProgram(shader))
814                {
815                    return gl::error(GL_INVALID_OPERATION);
816                }
817                else
818                {
819                    return gl::error(GL_INVALID_VALUE);
820                }
821            }
822
823            shaderObject->compile();
824        }
825    }
826    catch (...)
827    {
828        return gl::error(GL_OUT_OF_MEMORY);
829    }
830}
831
832void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
833                                      GLint border, GLsizei imageSize, const GLvoid* data)
834{
835    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
836          "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
837          target, level, internalformat, width, height, border, imageSize, data);
838
839    try
840    {
841        gl::Context *context = gl::getNonLostContext();
842
843        if (context)
844        {
845            if (context->getClientVersion() < 3 &&
846                !ValidateES2TexImageParameters(context, target, level, internalformat, true, false,
847                                               0, 0, width, height, border, GL_NONE, GL_NONE, data))
848            {
849                return;
850            }
851
852            if (context->getClientVersion() >= 3 &&
853                !ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
854                                               0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data))
855            {
856                return;
857            }
858
859            if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height))
860            {
861                return gl::error(GL_INVALID_VALUE);
862            }
863
864            switch (target)
865            {
866              case GL_TEXTURE_2D:
867                {
868                    gl::Texture2D *texture = context->getTexture2D();
869                    texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
870                }
871                break;
872
873              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
874              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
875              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
876              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
877              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
878              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
879                {
880                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
881                    texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
882                }
883                break;
884
885              default:
886                return gl::error(GL_INVALID_ENUM);
887            }
888        }
889    }
890    catch (...)
891    {
892        return gl::error(GL_OUT_OF_MEMORY);
893    }
894}
895
896void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
897                                         GLenum format, GLsizei imageSize, const GLvoid* data)
898{
899    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
900          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
901          "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
902          target, level, xoffset, yoffset, width, height, format, imageSize, data);
903
904    try
905    {
906        gl::Context *context = gl::getNonLostContext();
907
908        if (context)
909        {
910            if (context->getClientVersion() < 3 &&
911                !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true,
912                                               xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data))
913            {
914                return;
915            }
916
917            if (context->getClientVersion() >= 3 &&
918                !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
919                                               xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data))
920            {
921                return;
922            }
923
924            if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height))
925            {
926                return gl::error(GL_INVALID_VALUE);
927            }
928
929            switch (target)
930            {
931              case GL_TEXTURE_2D:
932                {
933                    gl::Texture2D *texture = context->getTexture2D();
934                    texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
935                }
936                break;
937
938              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
939              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
940              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
941              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
942              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
943              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
944                {
945                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
946                    texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
947                }
948                break;
949
950              default:
951                return gl::error(GL_INVALID_ENUM);
952            }
953        }
954    }
955    catch (...)
956    {
957        return gl::error(GL_OUT_OF_MEMORY);
958    }
959}
960
961void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
962{
963    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
964          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
965          target, level, internalformat, x, y, width, height, border);
966
967    try
968    {
969        gl::Context *context = gl::getNonLostContext();
970
971        if (context)
972        {
973            if (context->getClientVersion() < 3 &&
974                !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false,
975                                                   0, 0, x, y, width, height, border))
976            {
977                return;
978            }
979
980            if (context->getClientVersion() >= 3 &&
981                !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false,
982                                                   0, 0, 0, x, y, width, height, border))
983            {
984                return;
985            }
986
987            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
988
989            switch (target)
990            {
991              case GL_TEXTURE_2D:
992                {
993                    gl::Texture2D *texture = context->getTexture2D();
994                    texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
995                }
996                break;
997
998              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
999              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1000              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1001              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1002              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1003              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1004                {
1005                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
1006                    texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1007                }
1008                break;
1009
1010             default:
1011                return gl::error(GL_INVALID_ENUM);
1012            }
1013        }
1014    }
1015    catch (...)
1016    {
1017        return gl::error(GL_OUT_OF_MEMORY);
1018    }
1019}
1020
1021void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1022{
1023    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1024          "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1025          target, level, xoffset, yoffset, x, y, width, height);
1026
1027    try
1028    {
1029        gl::Context *context = gl::getNonLostContext();
1030
1031        if (context)
1032        {
1033            if (context->getClientVersion() < 3 &&
1034                !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true,
1035                                                   xoffset, yoffset, x, y, width, height, 0))
1036            {
1037                return;
1038            }
1039
1040            if (context->getClientVersion() >= 3 &&
1041                !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true,
1042                                                   xoffset, yoffset, 0, x, y, width, height, 0))
1043            {
1044                return;
1045            }
1046
1047            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
1048
1049            switch (target)
1050            {
1051              case GL_TEXTURE_2D:
1052                {
1053                    gl::Texture2D *texture = context->getTexture2D();
1054                    texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
1055                }
1056                break;
1057
1058              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1059              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1060              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1061              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1062              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1063              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1064                {
1065                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
1066                    texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
1067                }
1068                break;
1069
1070              default:
1071                return gl::error(GL_INVALID_ENUM);
1072            }
1073        }
1074    }
1075
1076    catch (...)
1077    {
1078        return gl::error(GL_OUT_OF_MEMORY);
1079    }
1080}
1081
1082GLuint __stdcall glCreateProgram(void)
1083{
1084    EVENT("()");
1085
1086    try
1087    {
1088        gl::Context *context = gl::getNonLostContext();
1089
1090        if (context)
1091        {
1092            return context->createProgram();
1093        }
1094    }
1095    catch (...)
1096    {
1097        return gl::error(GL_OUT_OF_MEMORY, 0);
1098    }
1099
1100    return 0;
1101}
1102
1103GLuint __stdcall glCreateShader(GLenum type)
1104{
1105    EVENT("(GLenum type = 0x%X)", type);
1106
1107    try
1108    {
1109        gl::Context *context = gl::getNonLostContext();
1110
1111        if (context)
1112        {
1113            switch (type)
1114            {
1115              case GL_FRAGMENT_SHADER:
1116              case GL_VERTEX_SHADER:
1117                return context->createShader(type);
1118              default:
1119                return gl::error(GL_INVALID_ENUM, 0);
1120            }
1121        }
1122    }
1123    catch (...)
1124    {
1125        return gl::error(GL_OUT_OF_MEMORY, 0);
1126    }
1127
1128    return 0;
1129}
1130
1131void __stdcall glCullFace(GLenum mode)
1132{
1133    EVENT("(GLenum mode = 0x%X)", mode);
1134
1135    try
1136    {
1137        switch (mode)
1138        {
1139          case GL_FRONT:
1140          case GL_BACK:
1141          case GL_FRONT_AND_BACK:
1142            {
1143                gl::Context *context = gl::getNonLostContext();
1144
1145                if (context)
1146                {
1147                    context->setCullMode(mode);
1148                }
1149            }
1150            break;
1151          default:
1152            return gl::error(GL_INVALID_ENUM);
1153        }
1154    }
1155    catch (...)
1156    {
1157        return gl::error(GL_OUT_OF_MEMORY);
1158    }
1159}
1160
1161void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers)
1162{
1163    EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
1164
1165    try
1166    {
1167        if (n < 0)
1168        {
1169            return gl::error(GL_INVALID_VALUE);
1170        }
1171
1172        gl::Context *context = gl::getNonLostContext();
1173
1174        if (context)
1175        {
1176            for (int i = 0; i < n; i++)
1177            {
1178                context->deleteBuffer(buffers[i]);
1179            }
1180        }
1181    }
1182    catch (...)
1183    {
1184        return gl::error(GL_OUT_OF_MEMORY);
1185    }
1186}
1187
1188void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences)
1189{
1190    EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
1191
1192    try
1193    {
1194        if (n < 0)
1195        {
1196            return gl::error(GL_INVALID_VALUE);
1197        }
1198
1199        gl::Context *context = gl::getNonLostContext();
1200
1201        if (context)
1202        {
1203            for (int i = 0; i < n; i++)
1204            {
1205                context->deleteFenceNV(fences[i]);
1206            }
1207        }
1208    }
1209    catch (...)
1210    {
1211        return gl::error(GL_OUT_OF_MEMORY);
1212    }
1213}
1214
1215void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1216{
1217    EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
1218
1219    try
1220    {
1221        if (n < 0)
1222        {
1223            return gl::error(GL_INVALID_VALUE);
1224        }
1225
1226        gl::Context *context = gl::getNonLostContext();
1227
1228        if (context)
1229        {
1230            for (int i = 0; i < n; i++)
1231            {
1232                if (framebuffers[i] != 0)
1233                {
1234                    context->deleteFramebuffer(framebuffers[i]);
1235                }
1236            }
1237        }
1238    }
1239    catch (...)
1240    {
1241        return gl::error(GL_OUT_OF_MEMORY);
1242    }
1243}
1244
1245void __stdcall glDeleteProgram(GLuint program)
1246{
1247    EVENT("(GLuint program = %d)", program);
1248
1249    try
1250    {
1251        if (program == 0)
1252        {
1253            return;
1254        }
1255
1256        gl::Context *context = gl::getNonLostContext();
1257
1258        if (context)
1259        {
1260            if (!context->getProgram(program))
1261            {
1262                if(context->getShader(program))
1263                {
1264                    return gl::error(GL_INVALID_OPERATION);
1265                }
1266                else
1267                {
1268                    return gl::error(GL_INVALID_VALUE);
1269                }
1270            }
1271
1272            context->deleteProgram(program);
1273        }
1274    }
1275    catch (...)
1276    {
1277        return gl::error(GL_OUT_OF_MEMORY);
1278    }
1279}
1280
1281void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
1282{
1283    EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
1284
1285    try
1286    {
1287        if (n < 0)
1288        {
1289            return gl::error(GL_INVALID_VALUE);
1290        }
1291
1292        gl::Context *context = gl::getNonLostContext();
1293
1294        if (context)
1295        {
1296            for (int i = 0; i < n; i++)
1297            {
1298                context->deleteQuery(ids[i]);
1299            }
1300        }
1301    }
1302    catch (...)
1303    {
1304        return gl::error(GL_OUT_OF_MEMORY);
1305    }
1306}
1307
1308void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1309{
1310    EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
1311
1312    try
1313    {
1314        if (n < 0)
1315        {
1316            return gl::error(GL_INVALID_VALUE);
1317        }
1318
1319        gl::Context *context = gl::getNonLostContext();
1320
1321        if (context)
1322        {
1323            for (int i = 0; i < n; i++)
1324            {
1325                context->deleteRenderbuffer(renderbuffers[i]);
1326            }
1327        }
1328    }
1329    catch (...)
1330    {
1331        return gl::error(GL_OUT_OF_MEMORY);
1332    }
1333}
1334
1335void __stdcall glDeleteShader(GLuint shader)
1336{
1337    EVENT("(GLuint shader = %d)", shader);
1338
1339    try
1340    {
1341        if (shader == 0)
1342        {
1343            return;
1344        }
1345
1346        gl::Context *context = gl::getNonLostContext();
1347
1348        if (context)
1349        {
1350            if (!context->getShader(shader))
1351            {
1352                if(context->getProgram(shader))
1353                {
1354                    return gl::error(GL_INVALID_OPERATION);
1355                }
1356                else
1357                {
1358                    return gl::error(GL_INVALID_VALUE);
1359                }
1360            }
1361
1362            context->deleteShader(shader);
1363        }
1364    }
1365    catch (...)
1366    {
1367        return gl::error(GL_OUT_OF_MEMORY);
1368    }
1369}
1370
1371void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures)
1372{
1373    EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
1374
1375    try
1376    {
1377        if (n < 0)
1378        {
1379            return gl::error(GL_INVALID_VALUE);
1380        }
1381
1382        gl::Context *context = gl::getNonLostContext();
1383
1384        if (context)
1385        {
1386            for (int i = 0; i < n; i++)
1387            {
1388                if (textures[i] != 0)
1389                {
1390                    context->deleteTexture(textures[i]);
1391                }
1392            }
1393        }
1394    }
1395    catch (...)
1396    {
1397        return gl::error(GL_OUT_OF_MEMORY);
1398    }
1399}
1400
1401void __stdcall glDepthFunc(GLenum func)
1402{
1403    EVENT("(GLenum func = 0x%X)", func);
1404
1405    try
1406    {
1407        switch (func)
1408        {
1409          case GL_NEVER:
1410          case GL_ALWAYS:
1411          case GL_LESS:
1412          case GL_LEQUAL:
1413          case GL_EQUAL:
1414          case GL_GREATER:
1415          case GL_GEQUAL:
1416          case GL_NOTEQUAL:
1417            break;
1418          default:
1419            return gl::error(GL_INVALID_ENUM);
1420        }
1421
1422        gl::Context *context = gl::getNonLostContext();
1423
1424        if (context)
1425        {
1426            context->setDepthFunc(func);
1427        }
1428    }
1429    catch (...)
1430    {
1431        return gl::error(GL_OUT_OF_MEMORY);
1432    }
1433}
1434
1435void __stdcall glDepthMask(GLboolean flag)
1436{
1437    EVENT("(GLboolean flag = %u)", flag);
1438
1439    try
1440    {
1441        gl::Context *context = gl::getNonLostContext();
1442
1443        if (context)
1444        {
1445            context->setDepthMask(flag != GL_FALSE);
1446        }
1447    }
1448    catch (...)
1449    {
1450        return gl::error(GL_OUT_OF_MEMORY);
1451    }
1452}
1453
1454void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar)
1455{
1456    EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1457
1458    try
1459    {
1460        gl::Context *context = gl::getNonLostContext();
1461
1462        if (context)
1463        {
1464            context->setDepthRange(zNear, zFar);
1465        }
1466    }
1467    catch (...)
1468    {
1469        return gl::error(GL_OUT_OF_MEMORY);
1470    }
1471}
1472
1473void __stdcall glDetachShader(GLuint program, GLuint shader)
1474{
1475    EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
1476
1477    try
1478    {
1479        gl::Context *context = gl::getNonLostContext();
1480
1481        if (context)
1482        {
1483
1484            gl::Program *programObject = context->getProgram(program);
1485            gl::Shader *shaderObject = context->getShader(shader);
1486
1487            if (!programObject)
1488            {
1489                gl::Shader *shaderByProgramHandle;
1490                shaderByProgramHandle = context->getShader(program);
1491                if (!shaderByProgramHandle)
1492                {
1493                    return gl::error(GL_INVALID_VALUE);
1494                }
1495                else
1496                {
1497                    return gl::error(GL_INVALID_OPERATION);
1498                }
1499            }
1500
1501            if (!shaderObject)
1502            {
1503                gl::Program *programByShaderHandle = context->getProgram(shader);
1504                if (!programByShaderHandle)
1505                {
1506                    return gl::error(GL_INVALID_VALUE);
1507                }
1508                else
1509                {
1510                    return gl::error(GL_INVALID_OPERATION);
1511                }
1512            }
1513
1514            if (!programObject->detachShader(shaderObject))
1515            {
1516                return gl::error(GL_INVALID_OPERATION);
1517            }
1518        }
1519    }
1520    catch (...)
1521    {
1522        return gl::error(GL_OUT_OF_MEMORY);
1523    }
1524}
1525
1526void __stdcall glDisable(GLenum cap)
1527{
1528    EVENT("(GLenum cap = 0x%X)", cap);
1529
1530    try
1531    {
1532        gl::Context *context = gl::getNonLostContext();
1533
1534        if (context)
1535        {
1536            if (!ValidCap(context, cap))
1537            {
1538                return gl::error(GL_INVALID_ENUM);
1539            }
1540
1541            context->setCap(cap, false);
1542        }
1543    }
1544    catch (...)
1545    {
1546        return gl::error(GL_OUT_OF_MEMORY);
1547    }
1548}
1549
1550void __stdcall glDisableVertexAttribArray(GLuint index)
1551{
1552    EVENT("(GLuint index = %d)", index);
1553
1554    try
1555    {
1556        if (index >= gl::MAX_VERTEX_ATTRIBS)
1557        {
1558            return gl::error(GL_INVALID_VALUE);
1559        }
1560
1561        gl::Context *context = gl::getNonLostContext();
1562
1563        if (context)
1564        {
1565            context->setEnableVertexAttribArray(index, false);
1566        }
1567    }
1568    catch (...)
1569    {
1570        return gl::error(GL_OUT_OF_MEMORY);
1571    }
1572}
1573
1574void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count)
1575{
1576    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1577
1578    try
1579    {
1580        if (count < 0 || first < 0)
1581        {
1582            return gl::error(GL_INVALID_VALUE);
1583        }
1584
1585        gl::Context *context = gl::getNonLostContext();
1586
1587        // Check for mapped buffers
1588        if (context->hasMappedBuffer(GL_ARRAY_BUFFER))
1589        {
1590            return gl::error(GL_INVALID_OPERATION);
1591        }
1592
1593        if (context)
1594        {
1595            gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback();
1596            if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() &&
1597                curTransformFeedback->getDrawMode() != mode)
1598            {
1599                // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
1600                // that does not match the current transform feedback object's draw mode (if transform feedback
1601                // is active), (3.0.2, section 2.14, pg 86)
1602                return gl::error(GL_INVALID_OPERATION);
1603            }
1604
1605            context->drawArrays(mode, first, count, 0);
1606        }
1607    }
1608    catch (...)
1609    {
1610        return gl::error(GL_OUT_OF_MEMORY);
1611    }
1612}
1613
1614void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1615{
1616    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
1617
1618    try
1619    {
1620        if (count < 0 || first < 0 || primcount < 0)
1621        {
1622            return gl::error(GL_INVALID_VALUE);
1623        }
1624
1625        if (primcount > 0)
1626        {
1627            gl::Context *context = gl::getNonLostContext();
1628
1629            // Check for mapped buffers
1630            if (context->hasMappedBuffer(GL_ARRAY_BUFFER))
1631            {
1632                return gl::error(GL_INVALID_OPERATION);
1633            }
1634
1635            if (context)
1636            {
1637                gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback();
1638                if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() &&
1639                    curTransformFeedback->getDrawMode() != mode)
1640                {
1641                    // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
1642                    // that does not match the current transform feedback object's draw mode (if transform feedback
1643                    // is active), (3.0.2, section 2.14, pg 86)
1644                    return gl::error(GL_INVALID_OPERATION);
1645                }
1646
1647                context->drawArrays(mode, first, count, primcount);
1648            }
1649        }
1650    }
1651    catch (...)
1652    {
1653        return gl::error(GL_OUT_OF_MEMORY);
1654    }
1655}
1656
1657void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1658{
1659    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
1660          mode, count, type, indices);
1661
1662    try
1663    {
1664        if (count < 0)
1665        {
1666            return gl::error(GL_INVALID_VALUE);
1667        }
1668
1669        gl::Context *context = gl::getNonLostContext();
1670
1671        if (context)
1672        {
1673            switch (type)
1674            {
1675              case GL_UNSIGNED_BYTE:
1676              case GL_UNSIGNED_SHORT:
1677                break;
1678              case GL_UNSIGNED_INT:
1679                if (!context->supports32bitIndices())
1680                {
1681                    return gl::error(GL_INVALID_ENUM);
1682                }
1683                break;
1684              default:
1685                return gl::error(GL_INVALID_ENUM);
1686            }
1687
1688            gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback();
1689            if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
1690            {
1691                // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
1692                // while transform feedback is active, (3.0.2, section 2.14, pg 86)
1693                return gl::error(GL_INVALID_OPERATION);
1694            }
1695
1696            // Check for mapped buffers
1697            if (context->hasMappedBuffer(GL_ARRAY_BUFFER) || context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
1698            {
1699                return gl::error(GL_INVALID_OPERATION);
1700            }
1701
1702            context->drawElements(mode, count, type, indices, 0);
1703        }
1704    }
1705    catch (...)
1706    {
1707        return gl::error(GL_OUT_OF_MEMORY);
1708    }
1709}
1710
1711void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
1712{
1713    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
1714          mode, count, type, indices, primcount);
1715
1716    try
1717    {
1718        if (count < 0 || primcount < 0)
1719        {
1720            return gl::error(GL_INVALID_VALUE);
1721        }
1722
1723        if (primcount > 0)
1724        {
1725            gl::Context *context = gl::getNonLostContext();
1726
1727            if (context)
1728            {
1729                switch (type)
1730                {
1731                  case GL_UNSIGNED_BYTE:
1732                  case GL_UNSIGNED_SHORT:
1733                    break;
1734                  case GL_UNSIGNED_INT:
1735                    if (!context->supports32bitIndices())
1736                    {
1737                        return gl::error(GL_INVALID_ENUM);
1738                    }
1739                    break;
1740                  default:
1741                    return gl::error(GL_INVALID_ENUM);
1742                }
1743
1744                gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback();
1745                if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
1746                {
1747                    // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
1748                    // while transform feedback is active, (3.0.2, section 2.14, pg 86)
1749                    return gl::error(GL_INVALID_OPERATION);
1750                }
1751
1752                // Check for mapped buffers
1753                if (context->hasMappedBuffer(GL_ARRAY_BUFFER) || context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
1754                {
1755                    return gl::error(GL_INVALID_OPERATION);
1756                }
1757
1758                context->drawElements(mode, count, type, indices, primcount);
1759            }
1760        }
1761    }
1762    catch (...)
1763    {
1764        return gl::error(GL_OUT_OF_MEMORY);
1765    }
1766}
1767
1768void __stdcall glEnable(GLenum cap)
1769{
1770    EVENT("(GLenum cap = 0x%X)", cap);
1771
1772    try
1773    {
1774        gl::Context *context = gl::getNonLostContext();
1775
1776        if (context)
1777        {
1778            if (!ValidCap(context, cap))
1779            {
1780                return gl::error(GL_INVALID_ENUM);
1781            }
1782
1783            context->setCap(cap, true);
1784        }
1785    }
1786    catch (...)
1787    {
1788        return gl::error(GL_OUT_OF_MEMORY);
1789    }
1790}
1791
1792void __stdcall glEnableVertexAttribArray(GLuint index)
1793{
1794    EVENT("(GLuint index = %d)", index);
1795
1796    try
1797    {
1798        if (index >= gl::MAX_VERTEX_ATTRIBS)
1799        {
1800            return gl::error(GL_INVALID_VALUE);
1801        }
1802
1803        gl::Context *context = gl::getNonLostContext();
1804
1805        if (context)
1806        {
1807            context->setEnableVertexAttribArray(index, true);
1808        }
1809    }
1810    catch (...)
1811    {
1812        return gl::error(GL_OUT_OF_MEMORY);
1813    }
1814}
1815
1816void __stdcall glEndQueryEXT(GLenum target)
1817{
1818    EVENT("GLenum target = 0x%X)", target);
1819
1820    try
1821    {
1822        gl::Context *context = gl::getNonLostContext();
1823
1824        if (context)
1825        {
1826            if (!ValidateEndQuery(context, target))
1827            {
1828                return;
1829            }
1830
1831            context->endQuery(target);
1832        }
1833    }
1834    catch (...)
1835    {
1836        return gl::error(GL_OUT_OF_MEMORY);
1837    }
1838}
1839
1840void __stdcall glFinishFenceNV(GLuint fence)
1841{
1842    EVENT("(GLuint fence = %d)", fence);
1843
1844    try
1845    {
1846        gl::Context *context = gl::getNonLostContext();
1847
1848        if (context)
1849        {
1850            gl::FenceNV *fenceObject = context->getFenceNV(fence);
1851
1852            if (fenceObject == NULL)
1853            {
1854                return gl::error(GL_INVALID_OPERATION);
1855            }
1856
1857            if (fenceObject->isFence() != GL_TRUE)
1858            {
1859                return gl::error(GL_INVALID_OPERATION);
1860            }
1861
1862            fenceObject->finishFence();
1863        }
1864    }
1865    catch (...)
1866    {
1867        return gl::error(GL_OUT_OF_MEMORY);
1868    }
1869}
1870
1871void __stdcall glFinish(void)
1872{
1873    EVENT("()");
1874
1875    try
1876    {
1877        gl::Context *context = gl::getNonLostContext();
1878
1879        if (context)
1880        {
1881            context->sync(true);
1882        }
1883    }
1884    catch (...)
1885    {
1886        return gl::error(GL_OUT_OF_MEMORY);
1887    }
1888}
1889
1890void __stdcall glFlush(void)
1891{
1892    EVENT("()");
1893
1894    try
1895    {
1896        gl::Context *context = gl::getNonLostContext();
1897
1898        if (context)
1899        {
1900            context->sync(false);
1901        }
1902    }
1903    catch (...)
1904    {
1905        return gl::error(GL_OUT_OF_MEMORY);
1906    }
1907}
1908
1909void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1910{
1911    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1912          "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1913
1914    try
1915    {
1916        if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1917        {
1918            return gl::error(GL_INVALID_ENUM);
1919        }
1920
1921        gl::Context *context = gl::getNonLostContext();
1922
1923        if (context)
1924        {
1925            if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer))
1926            {
1927                return;
1928            }
1929
1930            gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
1931            ASSERT(framebuffer);
1932
1933            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1934            {
1935                unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1936                framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0);
1937            }
1938            else
1939            {
1940                switch (attachment)
1941                {
1942                  case GL_DEPTH_ATTACHMENT:
1943                    framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
1944                    break;
1945                  case GL_STENCIL_ATTACHMENT:
1946                    framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
1947                    break;
1948                  case GL_DEPTH_STENCIL_ATTACHMENT:
1949                    framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0);
1950                    break;
1951                  default:
1952                    UNREACHABLE();
1953                    break;
1954                }
1955            }
1956        }
1957    }
1958    catch (...)
1959    {
1960        return gl::error(GL_OUT_OF_MEMORY);
1961    }
1962}
1963
1964void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1965{
1966    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1967          "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1968
1969    try
1970    {
1971        gl::Context *context = gl::getNonLostContext();
1972        if (context)
1973        {
1974            if (context->getClientVersion() < 3 &&
1975                !ValidateES2FramebufferTextureParameters(context, target, attachment, textarget, texture, level))
1976            {
1977                return;
1978            }
1979
1980            if (context->getClientVersion() >= 3 &&
1981                !ValidateES3FramebufferTextureParameters(context, target, attachment, textarget, texture, level, 0, false))
1982            {
1983                return;
1984            }
1985
1986            if (texture == 0)
1987            {
1988                textarget = GL_NONE;
1989            }
1990
1991            gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
1992
1993            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1994            {
1995                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1996                framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0);
1997            }
1998            else
1999            {
2000                switch (attachment)
2001                {
2002                  case GL_DEPTH_ATTACHMENT:         framebuffer->setDepthbuffer(textarget, texture, level, 0);        break;
2003                  case GL_STENCIL_ATTACHMENT:       framebuffer->setStencilbuffer(textarget, texture, level, 0);      break;
2004                  case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break;
2005                }
2006            }
2007        }
2008    }
2009    catch (...)
2010    {
2011        return gl::error(GL_OUT_OF_MEMORY);
2012    }
2013}
2014
2015void __stdcall glFrontFace(GLenum mode)
2016{
2017    EVENT("(GLenum mode = 0x%X)", mode);
2018
2019    try
2020    {
2021        switch (mode)
2022        {
2023          case GL_CW:
2024          case GL_CCW:
2025            {
2026                gl::Context *context = gl::getNonLostContext();
2027
2028                if (context)
2029                {
2030                    context->setFrontFace(mode);
2031                }
2032            }
2033            break;
2034          default:
2035            return gl::error(GL_INVALID_ENUM);
2036        }
2037    }
2038    catch (...)
2039    {
2040        return gl::error(GL_OUT_OF_MEMORY);
2041    }
2042}
2043
2044void __stdcall glGenBuffers(GLsizei n, GLuint* buffers)
2045{
2046    EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
2047
2048    try
2049    {
2050        if (n < 0)
2051        {
2052            return gl::error(GL_INVALID_VALUE);
2053        }
2054
2055        gl::Context *context = gl::getNonLostContext();
2056
2057        if (context)
2058        {
2059            for (int i = 0; i < n; i++)
2060            {
2061                buffers[i] = context->createBuffer();
2062            }
2063        }
2064    }
2065    catch (...)
2066    {
2067        return gl::error(GL_OUT_OF_MEMORY);
2068    }
2069}
2070
2071void __stdcall glGenerateMipmap(GLenum target)
2072{
2073    EVENT("(GLenum target = 0x%X)", target);
2074
2075    try
2076    {
2077        gl::Context *context = gl::getNonLostContext();
2078
2079        if (context)
2080        {
2081            if (!ValidTextureTarget(context, target))
2082            {
2083                return gl::error(GL_INVALID_ENUM);
2084            }
2085
2086            gl::Texture *texture = context->getTargetTexture(target);
2087
2088            if (texture == NULL)
2089            {
2090                return gl::error(GL_INVALID_OPERATION);
2091            }
2092
2093            GLenum internalFormat = texture->getBaseLevelInternalFormat();
2094
2095            // Internally, all texture formats are sized so checking if the format
2096            // is color renderable and filterable will not fail.
2097
2098            bool validRenderable = (gl::IsColorRenderingSupported(internalFormat, context) ||
2099                                    gl::IsSizedInternalFormat(internalFormat, context->getClientVersion()));
2100
2101            if (gl::IsDepthRenderingSupported(internalFormat, context) ||
2102                gl::IsFormatCompressed(internalFormat, context->getClientVersion()) ||
2103                !gl::IsTextureFilteringSupported(internalFormat, context) ||
2104                !validRenderable)
2105            {
2106                return gl::error(GL_INVALID_OPERATION);
2107            }
2108
2109            // Non-power of 2 ES2 check
2110            if (!context->supportsNonPower2Texture() && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight())))
2111            {
2112                ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
2113                return gl::error(GL_INVALID_OPERATION);
2114            }
2115
2116            // Cube completeness check
2117            if (target == GL_TEXTURE_CUBE_MAP)
2118            {
2119                gl::TextureCubeMap *textureCube = static_cast<gl::TextureCubeMap *>(texture);
2120                if (!textureCube->isCubeComplete())
2121                {
2122                    return gl::error(GL_INVALID_OPERATION);
2123                }
2124            }
2125
2126            texture->generateMipmaps();
2127        }
2128    }
2129    catch (...)
2130    {
2131        return gl::error(GL_OUT_OF_MEMORY);
2132    }
2133}
2134
2135void __stdcall glGenFencesNV(GLsizei n, GLuint* fences)
2136{
2137    EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
2138
2139    try
2140    {
2141        if (n < 0)
2142        {
2143            return gl::error(GL_INVALID_VALUE);
2144        }
2145
2146        gl::Context *context = gl::getNonLostContext();
2147
2148        if (context)
2149        {
2150            for (int i = 0; i < n; i++)
2151            {
2152                fences[i] = context->createFenceNV();
2153            }
2154        }
2155    }
2156    catch (...)
2157    {
2158        return gl::error(GL_OUT_OF_MEMORY);
2159    }
2160}
2161
2162void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers)
2163{
2164    EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
2165
2166    try
2167    {
2168        if (n < 0)
2169        {
2170            return gl::error(GL_INVALID_VALUE);
2171        }
2172
2173        gl::Context *context = gl::getNonLostContext();
2174
2175        if (context)
2176        {
2177            for (int i = 0; i < n; i++)
2178            {
2179                framebuffers[i] = context->createFramebuffer();
2180            }
2181        }
2182    }
2183    catch (...)
2184    {
2185        return gl::error(GL_OUT_OF_MEMORY);
2186    }
2187}
2188
2189void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids)
2190{
2191    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
2192
2193    try
2194    {
2195        gl::Context *context = gl::getNonLostContext();
2196
2197        if (context)
2198        {
2199            if (n < 0)
2200            {
2201                return gl::error(GL_INVALID_VALUE);
2202            }
2203
2204            for (GLsizei i = 0; i < n; i++)
2205            {
2206                ids[i] = context->createQuery();
2207            }
2208        }
2209    }
2210    catch (...)
2211    {
2212        return gl::error(GL_OUT_OF_MEMORY);
2213    }
2214}
2215
2216void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2217{
2218    EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
2219
2220    try
2221    {
2222        if (n < 0)
2223        {
2224            return gl::error(GL_INVALID_VALUE);
2225        }
2226
2227        gl::Context *context = gl::getNonLostContext();
2228
2229        if (context)
2230        {
2231            for (int i = 0; i < n; i++)
2232            {
2233                renderbuffers[i] = context->createRenderbuffer();
2234            }
2235        }
2236    }
2237    catch (...)
2238    {
2239        return gl::error(GL_OUT_OF_MEMORY);
2240    }
2241}
2242
2243void __stdcall glGenTextures(GLsizei n, GLuint* textures)
2244{
2245    EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
2246
2247    try
2248    {
2249        if (n < 0)
2250        {
2251            return gl::error(GL_INVALID_VALUE);
2252        }
2253
2254        gl::Context *context = gl::getNonLostContext();
2255
2256        if (context)
2257        {
2258            for (int i = 0; i < n; i++)
2259            {
2260                textures[i] = context->createTexture();
2261            }
2262        }
2263    }
2264    catch (...)
2265    {
2266        return gl::error(GL_OUT_OF_MEMORY);
2267    }
2268}
2269
2270void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2271{
2272    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
2273          "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
2274          program, index, bufsize, length, size, type, name);
2275
2276    try
2277    {
2278        if (bufsize < 0)
2279        {
2280            return gl::error(GL_INVALID_VALUE);
2281        }
2282
2283        gl::Context *context = gl::getNonLostContext();
2284
2285        if (context)
2286        {
2287            gl::Program *programObject = context->getProgram(program);
2288
2289            if (!programObject)
2290            {
2291                if (context->getShader(program))
2292                {
2293                    return gl::error(GL_INVALID_OPERATION);
2294                }
2295                else
2296                {
2297                    return gl::error(GL_INVALID_VALUE);
2298                }
2299            }
2300
2301            if (index >= (GLuint)programObject->getActiveAttributeCount())
2302            {
2303                return gl::error(GL_INVALID_VALUE);
2304            }
2305
2306            programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2307        }
2308    }
2309    catch (...)
2310    {
2311        return gl::error(GL_OUT_OF_MEMORY);
2312    }
2313}
2314
2315void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2316{
2317    EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2318          "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
2319          program, index, bufsize, length, size, type, name);
2320
2321    try
2322    {
2323        if (bufsize < 0)
2324        {
2325            return gl::error(GL_INVALID_VALUE);
2326        }
2327
2328        gl::Context *context = gl::getNonLostContext();
2329
2330        if (context)
2331        {
2332            gl::Program *programObject = context->getProgram(program);
2333
2334            if (!programObject)
2335            {
2336                if (context->getShader(program))
2337                {
2338                    return gl::error(GL_INVALID_OPERATION);
2339                }
2340                else
2341                {
2342                    return gl::error(GL_INVALID_VALUE);
2343                }
2344            }
2345
2346            if (index >= (GLuint)programObject->getActiveUniformCount())
2347            {
2348                return gl::error(GL_INVALID_VALUE);
2349            }
2350
2351            programObject->getActiveUniform(index, bufsize, length, size, type, name);
2352        }
2353    }
2354    catch (...)
2355    {
2356        return gl::error(GL_OUT_OF_MEMORY);
2357    }
2358}
2359
2360void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2361{
2362    EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
2363          program, maxcount, count, shaders);
2364
2365    try
2366    {
2367        if (maxcount < 0)
2368        {
2369            return gl::error(GL_INVALID_VALUE);
2370        }
2371
2372        gl::Context *context = gl::getNonLostContext();
2373
2374        if (context)
2375        {
2376            gl::Program *programObject = context->getProgram(program);
2377
2378            if (!programObject)
2379            {
2380                if (context->getShader(program))
2381                {
2382                    return gl::error(GL_INVALID_OPERATION);
2383                }
2384                else
2385                {
2386                    return gl::error(GL_INVALID_VALUE);
2387                }
2388            }
2389
2390            return programObject->getAttachedShaders(maxcount, count, shaders);
2391        }
2392    }
2393    catch (...)
2394    {
2395        return gl::error(GL_OUT_OF_MEMORY);
2396    }
2397}
2398
2399int __stdcall glGetAttribLocation(GLuint program, const GLchar* name)
2400{
2401    EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
2402
2403    try
2404    {
2405        gl::Context *context = gl::getNonLostContext();
2406
2407        if (context)
2408        {
2409
2410            gl::Program *programObject = context->getProgram(program);
2411
2412            if (!programObject)
2413            {
2414                if (context->getShader(program))
2415                {
2416                    return gl::error(GL_INVALID_OPERATION, -1);
2417                }
2418                else
2419                {
2420                    return gl::error(GL_INVALID_VALUE, -1);
2421                }
2422            }
2423
2424            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
2425            if (!programObject->isLinked() || !programBinary)
2426            {
2427                return gl::error(GL_INVALID_OPERATION, -1);
2428            }
2429
2430            return programBinary->getAttributeLocation(name);
2431        }
2432    }
2433    catch (...)
2434    {
2435        return gl::error(GL_OUT_OF_MEMORY, -1);
2436    }
2437
2438    return -1;
2439}
2440
2441void __stdcall glGetBooleanv(GLenum pname, GLboolean* params)
2442{
2443    EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
2444
2445    try
2446    {
2447        gl::Context *context = gl::getNonLostContext();
2448
2449        if (context)
2450        {
2451            GLenum nativeType;
2452            unsigned int numParams = 0;
2453            if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
2454            {
2455                return;
2456            }
2457
2458            if (nativeType == GL_BOOL)
2459            {
2460                context->getBooleanv(pname, params);
2461            }
2462            else
2463            {
2464                CastStateValues(context, nativeType, pname, numParams, params);
2465            }
2466        }
2467    }
2468    catch (...)
2469    {
2470        return gl::error(GL_OUT_OF_MEMORY);
2471    }
2472}
2473
2474void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2475{
2476    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
2477
2478    try
2479    {
2480        gl::Context *context = gl::getNonLostContext();
2481
2482        if (context)
2483        {
2484            if (!gl::ValidBufferTarget(context, target))
2485            {
2486                return gl::error(GL_INVALID_ENUM);
2487            }
2488
2489            if (!gl::ValidBufferParameter(context, pname))
2490            {
2491                return gl::error(GL_INVALID_ENUM);
2492            }
2493
2494            gl::Buffer *buffer = context->getTargetBuffer(target);
2495
2496            if (!buffer)
2497            {
2498                // A null buffer means that "0" is bound to the requested buffer target
2499                return gl::error(GL_INVALID_OPERATION);
2500            }
2501
2502            switch (pname)
2503            {
2504              case GL_BUFFER_USAGE:
2505                *params = static_cast<GLint>(buffer->usage());
2506                break;
2507              case GL_BUFFER_SIZE:
2508                *params = gl::clampCast<GLint>(buffer->size());
2509                break;
2510              case GL_BUFFER_ACCESS_FLAGS:
2511                *params = buffer->accessFlags();
2512                break;
2513              case GL_BUFFER_MAPPED:
2514                *params = static_cast<GLint>(buffer->mapped());
2515                break;
2516              case GL_BUFFER_MAP_OFFSET:
2517                *params = gl::clampCast<GLint>(buffer->mapOffset());
2518                break;
2519              case GL_BUFFER_MAP_LENGTH:
2520                *params = gl::clampCast<GLint>(buffer->mapLength());
2521                break;
2522              default: UNREACHABLE(); break;
2523            }
2524        }
2525    }
2526    catch (...)
2527    {
2528        return gl::error(GL_OUT_OF_MEMORY);
2529    }
2530}
2531
2532GLenum __stdcall glGetError(void)
2533{
2534    EVENT("()");
2535
2536    gl::Context *context = gl::getContext();
2537
2538    if (context)
2539    {
2540        return context->getError();
2541    }
2542
2543    return GL_NO_ERROR;
2544}
2545
2546void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2547{
2548    EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
2549
2550    try
2551    {
2552
2553        gl::Context *context = gl::getNonLostContext();
2554
2555        if (context)
2556        {
2557            gl::FenceNV *fenceObject = context->getFenceNV(fence);
2558
2559            if (fenceObject == NULL)
2560            {
2561                return gl::error(GL_INVALID_OPERATION);
2562            }
2563
2564            if (fenceObject->isFence() != GL_TRUE)
2565            {
2566                return gl::error(GL_INVALID_OPERATION);
2567            }
2568
2569            switch (pname)
2570            {
2571              case GL_FENCE_STATUS_NV:
2572              case GL_FENCE_CONDITION_NV:
2573                break;
2574
2575              default: return gl::error(GL_INVALID_ENUM);
2576            }
2577
2578            params[0] = fenceObject->getFencei(pname);
2579        }
2580    }
2581    catch (...)
2582    {
2583        return gl::error(GL_OUT_OF_MEMORY);
2584    }
2585}
2586
2587void __stdcall glGetFloatv(GLenum pname, GLfloat* params)
2588{
2589    EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
2590
2591    try
2592    {
2593        gl::Context *context = gl::getNonLostContext();
2594
2595        if (context)
2596        {
2597            GLenum nativeType;
2598            unsigned int numParams = 0;
2599            if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
2600            {
2601                return;
2602            }
2603
2604            if (nativeType == GL_FLOAT)
2605            {
2606                context->getFloatv(pname, params);
2607            }
2608            else
2609            {
2610                CastStateValues(context, nativeType, pname, numParams, params);
2611            }
2612        }
2613    }
2614    catch (...)
2615    {
2616        return gl::error(GL_OUT_OF_MEMORY);
2617    }
2618}
2619
2620void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2621{
2622    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
2623          target, attachment, pname, params);
2624
2625    try
2626    {
2627        gl::Context *context = gl::getNonLostContext();
2628
2629        if (context)
2630        {
2631            if (!gl::ValidFramebufferTarget(target))
2632            {
2633                return gl::error(GL_INVALID_ENUM);
2634            }
2635
2636            switch (pname)
2637            {
2638              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2639              case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2640              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2641              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2642                break;
2643              case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2644              case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2645              case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2646              case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2647              case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2648              case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2649              case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2650              case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2651              case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2652                if (context->getClientVersion() >= 3)
2653                {
2654                    break;
2655                }
2656              default:
2657                return gl::error(GL_INVALID_ENUM);
2658            }
2659
2660            // Determine if the attachment is a valid enum
2661            switch (attachment)
2662            {
2663              case GL_BACK:
2664              case GL_FRONT:
2665              case GL_DEPTH:
2666              case GL_STENCIL:
2667              case GL_DEPTH_STENCIL_ATTACHMENT:
2668                if (context->getClientVersion() < 3)
2669                {
2670                    return gl::error(GL_INVALID_ENUM);
2671                }
2672                break;
2673
2674              case GL_DEPTH_ATTACHMENT:
2675              case GL_STENCIL_ATTACHMENT:
2676                break;
2677
2678              default:
2679                if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
2680                    (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getMaximumRenderTargets())
2681                {
2682                    return gl::error(GL_INVALID_ENUM);
2683                }
2684                break;
2685            }
2686
2687            GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
2688            ASSERT(framebufferHandle != GL_INVALID_INDEX);
2689            gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle);
2690
2691            GLenum attachmentType;
2692            GLuint attachmentHandle;
2693            GLuint attachmentLevel;
2694            GLuint attachmentLayer;
2695            gl::FramebufferAttachment *attachmentObject;
2696
2697            if (framebufferHandle == 0)
2698            {
2699                if (context->getClientVersion() < 3)
2700                {
2701                    return gl::error(GL_INVALID_OPERATION);
2702                }
2703
2704                switch (attachment)
2705                {
2706                  case GL_BACK:
2707                    attachmentType = framebuffer->getColorbufferType(0);
2708                    attachmentHandle = framebuffer->getColorbufferHandle(0);
2709                    attachmentLevel = framebuffer->getColorbufferMipLevel(0);
2710                    attachmentLayer = framebuffer->getColorbufferLayer(0);
2711                    attachmentObject = framebuffer->getColorbuffer(0);
2712                    break;
2713                  case GL_DEPTH:
2714                    attachmentType = framebuffer->getDepthbufferType();
2715                    attachmentHandle = framebuffer->getDepthbufferHandle();
2716                    attachmentLevel = framebuffer->getDepthbufferMipLevel();
2717                    attachmentLayer = framebuffer->getDepthbufferLayer();
2718                    attachmentObject = framebuffer->getDepthbuffer();
2719                    break;
2720                  case GL_STENCIL:
2721                    attachmentType = framebuffer->getStencilbufferType();
2722                    attachmentHandle = framebuffer->getStencilbufferHandle();
2723                    attachmentLevel = framebuffer->getStencilbufferMipLevel();
2724                    attachmentLayer = framebuffer->getStencilbufferLayer();
2725                    attachmentObject = framebuffer->getStencilbuffer();
2726                    break;
2727                  default:
2728                    return gl::error(GL_INVALID_OPERATION);
2729                }
2730            }
2731            else
2732            {
2733                if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
2734                {
2735                    const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
2736                    attachmentType = framebuffer->getColorbufferType(colorAttachment);
2737                    attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment);
2738                    attachmentLevel = framebuffer->getColorbufferMipLevel(colorAttachment);
2739                    attachmentLayer = framebuffer->getColorbufferLayer(colorAttachment);
2740                    attachmentObject = framebuffer->getColorbuffer(colorAttachment);
2741                }
2742                else
2743                {
2744                    switch (attachment)
2745                    {
2746                      case GL_DEPTH_ATTACHMENT:
2747                        attachmentType = framebuffer->getDepthbufferType();
2748                        attachmentHandle = framebuffer->getDepthbufferHandle();
2749                        attachmentLevel = framebuffer->getDepthbufferMipLevel();
2750                        attachmentLayer = framebuffer->getDepthbufferLayer();
2751                        attachmentObject = framebuffer->getDepthbuffer();
2752                        break;
2753                      case GL_STENCIL_ATTACHMENT:
2754                        attachmentType = framebuffer->getStencilbufferType();
2755                        attachmentHandle = framebuffer->getStencilbufferHandle();
2756                        attachmentLevel = framebuffer->getStencilbufferMipLevel();
2757                        attachmentLayer = framebuffer->getStencilbufferLayer();
2758                        attachmentObject = framebuffer->getStencilbuffer();
2759                        break;
2760                      case GL_DEPTH_STENCIL_ATTACHMENT:
2761                        if (framebuffer->getDepthbufferHandle() != framebuffer->getStencilbufferHandle())
2762                        {
2763                            return gl::error(GL_INVALID_OPERATION);
2764                        }
2765                        attachmentType = framebuffer->getDepthStencilbufferType();
2766                        attachmentHandle = framebuffer->getDepthStencilbufferHandle();
2767                        attachmentLevel = framebuffer->getDepthStencilbufferMipLevel();
2768                        attachmentLayer = framebuffer->getDepthStencilbufferLayer();
2769                        attachmentObject = framebuffer->getDepthStencilBuffer();
2770                        break;
2771                      default:
2772                        return gl::error(GL_INVALID_OPERATION);
2773                    }
2774                }
2775            }
2776
2777            GLenum attachmentObjectType;   // Type category
2778            if (framebufferHandle == 0)
2779            {
2780                attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2781            }
2782            else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
2783            {
2784                attachmentObjectType = attachmentType;
2785            }
2786            else if (gl::IsInternalTextureTarget(attachmentType, context->getClientVersion()))
2787            {
2788                attachmentObjectType = GL_TEXTURE;
2789            }
2790            else
2791            {
2792                UNREACHABLE();
2793                return;
2794            }
2795
2796            if (attachmentObjectType == GL_NONE)
2797            {
2798                // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2799                // is NONE, then querying any other pname will generate INVALID_ENUM.
2800
2801                // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2802                // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2803                // INVALID_OPERATION for all other pnames
2804
2805                switch (pname)
2806                {
2807                  case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2808                    *params = attachmentObjectType;
2809                    break;
2810
2811                  case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2812                    if (context->getClientVersion() < 3)
2813                    {
2814                        return gl::error(GL_INVALID_ENUM);
2815                    }
2816                    *params = 0;
2817                    break;
2818
2819                  default:
2820                    if (context->getClientVersion() < 3)
2821                    {
2822                        return gl::error(GL_INVALID_ENUM);
2823                    }
2824                    else
2825                    {
2826                        gl::error(GL_INVALID_OPERATION);
2827                    }
2828                }
2829            }
2830            else
2831            {
2832                ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE ||
2833                       attachmentObjectType == GL_FRAMEBUFFER_DEFAULT);
2834                ASSERT(attachmentObject != NULL);
2835
2836                switch (pname)
2837                {
2838                  case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2839                    *params = attachmentObjectType;
2840                    break;
2841
2842                  case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2843                    if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE)
2844                    {
2845                        return gl::error(GL_INVALID_ENUM);
2846                    }
2847                    *params = attachmentHandle;
2848                    break;
2849
2850                  case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2851                    if (attachmentObjectType != GL_TEXTURE)
2852                    {
2853                        return gl::error(GL_INVALID_ENUM);
2854                    }
2855                    *params = attachmentLevel;
2856                    break;
2857
2858                  case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2859                    if (attachmentObjectType != GL_TEXTURE)
2860                    {
2861                        return gl::error(GL_INVALID_ENUM);
2862                    }
2863                    *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0;
2864                    break;
2865
2866                  case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2867                    *params = attachmentObject->getRedSize();
2868                    break;
2869
2870                  case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2871                    *params = attachmentObject->getGreenSize();
2872                    break;
2873
2874                  case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2875                    *params = attachmentObject->getBlueSize();
2876                    break;
2877
2878                  case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2879                    *params = attachmentObject->getAlphaSize();
2880                    break;
2881
2882                  case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2883                    *params = attachmentObject->getDepthSize();
2884                    break;
2885
2886                  case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2887                    *params = attachmentObject->getStencilSize();
2888                    break;
2889
2890                  case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2891                    if (attachment == GL_DEPTH_STENCIL)
2892                    {
2893                        gl::error(GL_INVALID_OPERATION);
2894                    }
2895                    *params = attachmentObject->getComponentType();
2896                    break;
2897
2898                  case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2899                    *params = attachmentObject->getColorEncoding();
2900                    break;
2901
2902                  case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2903                    if (attachmentObjectType != GL_TEXTURE)
2904                    {
2905                        return gl::error(GL_INVALID_ENUM);
2906                    }
2907                    *params = attachmentLayer;
2908                    break;
2909
2910                  default:
2911                    UNREACHABLE();
2912                    break;
2913                }
2914            }
2915        }
2916    }
2917    catch (...)
2918    {
2919        return gl::error(GL_OUT_OF_MEMORY);
2920    }
2921}
2922
2923GLenum __stdcall glGetGraphicsResetStatusEXT(void)
2924{
2925    EVENT("()");
2926
2927    try
2928    {
2929        gl::Context *context = gl::getContext();
2930
2931        if (context)
2932        {
2933            return context->getResetStatus();
2934        }
2935
2936        return GL_NO_ERROR;
2937    }
2938    catch (...)
2939    {
2940        return GL_OUT_OF_MEMORY;
2941    }
2942}
2943
2944void __stdcall glGetIntegerv(GLenum pname, GLint* params)
2945{
2946    EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
2947
2948    try
2949    {
2950        gl::Context *context = gl::getNonLostContext();
2951
2952        if (context)
2953        {
2954            GLenum nativeType;
2955            unsigned int numParams = 0;
2956
2957            if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
2958            {
2959                return;
2960            }
2961
2962            if (nativeType == GL_INT)
2963            {
2964                context->getIntegerv(pname, params);
2965            }
2966            else
2967            {
2968                CastStateValues(context, nativeType, pname, numParams, params);
2969            }
2970        }
2971    }
2972    catch (...)
2973    {
2974        return gl::error(GL_OUT_OF_MEMORY);
2975    }
2976}
2977
2978void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params)
2979{
2980    EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
2981
2982    try
2983    {
2984        gl::Context *context = gl::getNonLostContext();
2985
2986        if (context)
2987        {
2988            gl::Program *programObject = context->getProgram(program);
2989
2990            if (!programObject)
2991            {
2992                return gl::error(GL_INVALID_VALUE);
2993            }
2994
2995            if (context->getClientVersion() < 3)
2996            {
2997                switch (pname)
2998                {
2999                  case GL_ACTIVE_UNIFORM_BLOCKS:
3000                  case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3001                  case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3002                  case GL_TRANSFORM_FEEDBACK_VARYINGS:
3003                  case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3004                    return gl::error(GL_INVALID_ENUM);
3005                }
3006            }
3007
3008            switch (pname)
3009            {
3010              case GL_DELETE_STATUS:
3011                *params = programObject->isFlaggedForDeletion();
3012                return;
3013              case GL_LINK_STATUS:
3014                *params = programObject->isLinked();
3015                return;
3016              case GL_VALIDATE_STATUS:
3017                *params = programObject->isValidated();
3018                return;
3019              case GL_INFO_LOG_LENGTH:
3020                *params = programObject->getInfoLogLength();
3021                return;
3022              case GL_ATTACHED_SHADERS:
3023                *params = programObject->getAttachedShadersCount();
3024                return;
3025              case GL_ACTIVE_ATTRIBUTES:
3026                *params = programObject->getActiveAttributeCount();
3027                return;
3028              case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3029                *params = programObject->getActiveAttributeMaxLength();
3030                return;
3031              case GL_ACTIVE_UNIFORMS:
3032                *params = programObject->getActiveUniformCount();
3033                return;
3034              case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3035                *params = programObject->getActiveUniformMaxLength();
3036                return;
3037              case GL_PROGRAM_BINARY_LENGTH_OES:
3038                *params = programObject->getProgramBinaryLength();
3039                return;
3040              case GL_ACTIVE_UNIFORM_BLOCKS:
3041                *params = programObject->getActiveUniformBlockCount();
3042                return;
3043              case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3044                *params = programObject->getActiveUniformBlockMaxLength();
3045                break;
3046              case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3047                *params = programObject->getTransformFeedbackBufferMode();
3048                break;
3049              case GL_TRANSFORM_FEEDBACK_VARYINGS:
3050                *params = programObject->getTransformFeedbackVaryingCount();
3051                break;
3052              case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3053                *params = programObject->getTransformFeedbackVaryingMaxLength();
3054                break;
3055              default:
3056                return gl::error(GL_INVALID_ENUM);
3057            }
3058        }
3059    }
3060    catch (...)
3061    {
3062        return gl::error(GL_OUT_OF_MEMORY);
3063    }
3064}
3065
3066void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3067{
3068    EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
3069          program, bufsize, length, infolog);
3070
3071    try
3072    {
3073        if (bufsize < 0)
3074        {
3075            return gl::error(GL_INVALID_VALUE);
3076        }
3077
3078        gl::Context *context = gl::getNonLostContext();
3079
3080        if (context)
3081        {
3082            gl::Program *programObject = context->getProgram(program);
3083
3084            if (!programObject)
3085            {
3086                return gl::error(GL_INVALID_VALUE);
3087            }
3088
3089            programObject->getInfoLog(bufsize, length, infolog);
3090        }
3091    }
3092    catch (...)
3093    {
3094        return gl::error(GL_OUT_OF_MEMORY);
3095    }
3096}
3097
3098void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3099{
3100    EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
3101
3102    try
3103    {
3104        gl::Context *context = gl::getNonLostContext();
3105
3106        if (context)
3107        {
3108            if (!ValidQueryType(context, target))
3109            {
3110                return gl::error(GL_INVALID_ENUM);
3111            }
3112
3113            switch (pname)
3114            {
3115              case GL_CURRENT_QUERY_EXT:
3116                params[0] = context->getActiveQueryId(target);
3117                break;
3118
3119              default:
3120                return gl::error(GL_INVALID_ENUM);
3121            }
3122        }
3123    }
3124    catch (...)
3125    {
3126        return gl::error(GL_OUT_OF_MEMORY);
3127    }
3128}
3129
3130void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
3131{
3132    EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
3133
3134    try
3135    {
3136        gl::Context *context = gl::getNonLostContext();
3137
3138        if (context)
3139        {
3140            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
3141
3142            if (!queryObject)
3143            {
3144                return gl::error(GL_INVALID_OPERATION);
3145            }
3146
3147            if (context->getActiveQueryId(queryObject->getType()) == id)
3148            {
3149                return gl::error(GL_INVALID_OPERATION);
3150            }
3151
3152            switch(pname)
3153            {
3154              case GL_QUERY_RESULT_EXT:
3155                params[0] = queryObject->getResult();
3156                break;
3157              case GL_QUERY_RESULT_AVAILABLE_EXT:
3158                params[0] = queryObject->isResultAvailable();
3159                break;
3160              default:
3161                return gl::error(GL_INVALID_ENUM);
3162            }
3163        }
3164    }
3165    catch (...)
3166    {
3167        return gl::error(GL_OUT_OF_MEMORY);
3168    }
3169}
3170
3171void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3172{
3173    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
3174
3175    try
3176    {
3177        gl::Context *context = gl::getNonLostContext();
3178
3179        if (context)
3180        {
3181            if (target != GL_RENDERBUFFER)
3182            {
3183                return gl::error(GL_INVALID_ENUM);
3184            }
3185
3186            if (context->getRenderbufferHandle() == 0)
3187            {
3188                return gl::error(GL_INVALID_OPERATION);
3189            }
3190
3191            gl::FramebufferAttachment *attachment = context->getRenderbuffer(context->getRenderbufferHandle());
3192
3193            switch (pname)
3194            {
3195              case GL_RENDERBUFFER_WIDTH:           *params = attachment->getWidth();          break;
3196              case GL_RENDERBUFFER_HEIGHT:          *params = attachment->getHeight();         break;
3197              case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = attachment->getInternalFormat(); break;
3198              case GL_RENDERBUFFER_RED_SIZE:        *params = attachment->getRedSize();        break;
3199              case GL_RENDERBUFFER_GREEN_SIZE:      *params = attachment->getGreenSize();      break;
3200              case GL_RENDERBUFFER_BLUE_SIZE:       *params = attachment->getBlueSize();       break;
3201              case GL_RENDERBUFFER_ALPHA_SIZE:      *params = attachment->getAlphaSize();      break;
3202              case GL_RENDERBUFFER_DEPTH_SIZE:      *params = attachment->getDepthSize();      break;
3203              case GL_RENDERBUFFER_STENCIL_SIZE:    *params = attachment->getStencilSize();    break;
3204              case GL_RENDERBUFFER_SAMPLES_ANGLE:
3205                if (context->getMaxSupportedSamples() != 0)
3206                {
3207                    *params = attachment->getSamples();
3208                }
3209                else
3210                {
3211                    return gl::error(GL_INVALID_ENUM);
3212                }
3213                break;
3214              default:
3215                return gl::error(GL_INVALID_ENUM);
3216            }
3217        }
3218    }
3219    catch (...)
3220    {
3221        return gl::error(GL_OUT_OF_MEMORY);
3222    }
3223}
3224
3225void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
3226{
3227    EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
3228
3229    try
3230    {
3231        gl::Context *context = gl::getNonLostContext();
3232
3233        if (context)
3234        {
3235            gl::Shader *shaderObject = context->getShader(shader);
3236
3237            if (!shaderObject)
3238            {
3239                return gl::error(GL_INVALID_VALUE);
3240            }
3241
3242            switch (pname)
3243            {
3244              case GL_SHADER_TYPE:
3245                *params = shaderObject->getType();
3246                return;
3247              case GL_DELETE_STATUS:
3248                *params = shaderObject->isFlaggedForDeletion();
3249                return;
3250              case GL_COMPILE_STATUS:
3251                *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3252                return;
3253              case GL_INFO_LOG_LENGTH:
3254                *params = shaderObject->getInfoLogLength();
3255                return;
3256              case GL_SHADER_SOURCE_LENGTH:
3257                *params = shaderObject->getSourceLength();
3258                return;
3259              case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
3260                *params = shaderObject->getTranslatedSourceLength();
3261                return;
3262              default:
3263                return gl::error(GL_INVALID_ENUM);
3264            }
3265        }
3266    }
3267    catch (...)
3268    {
3269        return gl::error(GL_OUT_OF_MEMORY);
3270    }
3271}
3272
3273void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3274{
3275    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
3276          shader, bufsize, length, infolog);
3277
3278    try
3279    {
3280        if (bufsize < 0)
3281        {
3282            return gl::error(GL_INVALID_VALUE);
3283        }
3284
3285        gl::Context *context = gl::getNonLostContext();
3286
3287        if (context)
3288        {
3289            gl::Shader *shaderObject = context->getShader(shader);
3290
3291            if (!shaderObject)
3292            {
3293                return gl::error(GL_INVALID_VALUE);
3294            }
3295
3296            shaderObject->getInfoLog(bufsize, length, infolog);
3297        }
3298    }
3299    catch (...)
3300    {
3301        return gl::error(GL_OUT_OF_MEMORY);
3302    }
3303}
3304
3305void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3306{
3307    EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
3308          shadertype, precisiontype, range, precision);
3309
3310    try
3311    {
3312        switch (shadertype)
3313        {
3314          case GL_VERTEX_SHADER:
3315          case GL_FRAGMENT_SHADER:
3316            break;
3317          default:
3318            return gl::error(GL_INVALID_ENUM);
3319        }
3320
3321        switch (precisiontype)
3322        {
3323          case GL_LOW_FLOAT:
3324          case GL_MEDIUM_FLOAT:
3325          case GL_HIGH_FLOAT:
3326            // Assume IEEE 754 precision
3327            range[0] = 127;
3328            range[1] = 127;
3329            *precision = 23;
3330            break;
3331          case GL_LOW_INT:
3332          case GL_MEDIUM_INT:
3333          case GL_HIGH_INT:
3334            // Some (most) hardware only supports single-precision floating-point numbers,
3335            // which can accurately represent integers up to +/-16777216
3336            range[0] = 24;
3337            range[1] = 24;
3338            *precision = 0;
3339            break;
3340          default:
3341            return gl::error(GL_INVALID_ENUM);
3342        }
3343    }
3344    catch (...)
3345    {
3346        return gl::error(GL_OUT_OF_MEMORY);
3347    }
3348}
3349
3350void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3351{
3352    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
3353          shader, bufsize, length, source);
3354
3355    try
3356    {
3357        if (bufsize < 0)
3358        {
3359            return gl::error(GL_INVALID_VALUE);
3360        }
3361
3362        gl::Context *context = gl::getNonLostContext();
3363
3364        if (context)
3365        {
3366            gl::Shader *shaderObject = context->getShader(shader);
3367
3368            if (!shaderObject)
3369            {
3370                return gl::error(GL_INVALID_OPERATION);
3371            }
3372
3373            shaderObject->getSource(bufsize, length, source);
3374        }
3375    }
3376    catch (...)
3377    {
3378        return gl::error(GL_OUT_OF_MEMORY);
3379    }
3380}
3381
3382void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3383{
3384    EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
3385          shader, bufsize, length, source);
3386
3387    try
3388    {
3389        if (bufsize < 0)
3390        {
3391            return gl::error(GL_INVALID_VALUE);
3392        }
3393
3394        gl::Context *context = gl::getNonLostContext();
3395
3396        if (context)
3397        {
3398            gl::Shader *shaderObject = context->getShader(shader);
3399
3400            if (!shaderObject)
3401            {
3402                return gl::error(GL_INVALID_OPERATION);
3403            }
3404
3405            shaderObject->getTranslatedSource(bufsize, length, source);
3406        }
3407    }
3408    catch (...)
3409    {
3410        return gl::error(GL_OUT_OF_MEMORY);
3411    }
3412}
3413
3414const GLubyte* __stdcall glGetString(GLenum name)
3415{
3416    EVENT("(GLenum name = 0x%X)", name);
3417
3418    try
3419    {
3420        gl::Context *context = gl::getNonLostContext();
3421
3422        switch (name)
3423        {
3424          case GL_VENDOR:
3425            return (GLubyte*)"Google Inc.";
3426          case GL_RENDERER:
3427            return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE");
3428          case GL_VERSION:
3429            if (context->getClientVersion() == 2)
3430            {
3431                return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")";
3432            }
3433            else
3434            {
3435                return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")";
3436            }
3437          case GL_SHADING_LANGUAGE_VERSION:
3438            if (context->getClientVersion() == 2)
3439            {
3440                return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")";
3441            }
3442            else
3443            {
3444                return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")";
3445            }
3446          case GL_EXTENSIONS:
3447            return (GLubyte*)((context != NULL) ? context->getCombinedExtensionsString() : "");
3448          default:
3449            return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL);
3450        }
3451    }
3452    catch (...)
3453    {
3454        return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
3455    }
3456}
3457
3458void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3459{
3460    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
3461
3462    try
3463    {
3464        gl::Context *context = gl::getNonLostContext();
3465
3466        if (context)
3467        {
3468            gl::Texture *texture = context->getTargetTexture(target);
3469
3470            if (!texture)
3471            {
3472                return gl::error(GL_INVALID_ENUM);
3473            }
3474
3475            switch (pname)
3476            {
3477              case GL_TEXTURE_MAG_FILTER:
3478                *params = (GLfloat)texture->getMagFilter();
3479                break;
3480              case GL_TEXTURE_MIN_FILTER:
3481                *params = (GLfloat)texture->getMinFilter();
3482                break;
3483              case GL_TEXTURE_WRAP_S:
3484                *params = (GLfloat)texture->getWrapS();
3485                break;
3486              case GL_TEXTURE_WRAP_T:
3487                *params = (GLfloat)texture->getWrapT();
3488                break;
3489              case GL_TEXTURE_WRAP_R:
3490                if (context->getClientVersion() < 3)
3491                {
3492                    return gl::error(GL_INVALID_ENUM);
3493                }
3494                *params = (GLfloat)texture->getWrapR();
3495                break;
3496              case GL_TEXTURE_IMMUTABLE_FORMAT:
3497                // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
3498                *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
3499                break;
3500              case GL_TEXTURE_IMMUTABLE_LEVELS:
3501                if (context->getClientVersion() < 3)
3502                {
3503                    return gl::error(GL_INVALID_ENUM);
3504                }
3505                *params = (GLfloat)texture->immutableLevelCount();
3506                break;
3507              case GL_TEXTURE_USAGE_ANGLE:
3508                *params = (GLfloat)texture->getUsage();
3509                break;
3510              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3511                if (!context->supportsTextureFilterAnisotropy())
3512                {
3513                    return gl::error(GL_INVALID_ENUM);
3514                }
3515                *params = (GLfloat)texture->getMaxAnisotropy();
3516                break;
3517              case GL_TEXTURE_SWIZZLE_R:
3518                if (context->getClientVersion() < 3)
3519                {
3520                    return gl::error(GL_INVALID_ENUM);
3521                }
3522                *params = (GLfloat)texture->getSwizzleRed();
3523                break;
3524              case GL_TEXTURE_SWIZZLE_G:
3525                if (context->getClientVersion() < 3)
3526                {
3527                    return gl::error(GL_INVALID_ENUM);
3528                }
3529                *params = (GLfloat)texture->getSwizzleGreen();
3530                break;
3531              case GL_TEXTURE_SWIZZLE_B:
3532                if (context->getClientVersion() < 3)
3533                {
3534                    return gl::error(GL_INVALID_ENUM);
3535                }
3536                *params = (GLfloat)texture->getSwizzleBlue();
3537                break;
3538              case GL_TEXTURE_SWIZZLE_A:
3539                if (context->getClientVersion() < 3)
3540                {
3541                    return gl::error(GL_INVALID_ENUM);
3542                }
3543                *params = (GLfloat)texture->getSwizzleAlpha();
3544                break;
3545              case GL_TEXTURE_BASE_LEVEL:
3546                if (context->getClientVersion() < 3)
3547                {
3548                    return gl::error(GL_INVALID_ENUM);
3549                }
3550                *params = (GLfloat)texture->getBaseLevel();
3551                break;
3552              case GL_TEXTURE_MAX_LEVEL:
3553                if (context->getClientVersion() < 3)
3554                {
3555                    return gl::error(GL_INVALID_ENUM);
3556                }
3557                *params = (GLfloat)texture->getMaxLevel();
3558                break;
3559              case GL_TEXTURE_MIN_LOD:
3560                if (context->getClientVersion() < 3)
3561                {
3562                    return gl::error(GL_INVALID_ENUM);
3563                }
3564                *params = texture->getMinLod();
3565                break;
3566              case GL_TEXTURE_MAX_LOD:
3567                if (context->getClientVersion() < 3)
3568                {
3569                    return gl::error(GL_INVALID_ENUM);
3570                }
3571                *params = texture->getMaxLod();
3572                break;
3573              default:
3574                return gl::error(GL_INVALID_ENUM);
3575            }
3576        }
3577    }
3578    catch (...)
3579    {
3580        return gl::error(GL_OUT_OF_MEMORY);
3581    }
3582}
3583
3584void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3585{
3586    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
3587
3588    try
3589    {
3590        gl::Context *context = gl::getNonLostContext();
3591
3592        if (context)
3593        {
3594            gl::Texture *texture = context->getTargetTexture(target);
3595
3596            if (!texture)
3597            {
3598                return gl::error(GL_INVALID_ENUM);
3599            }
3600
3601            switch (pname)
3602            {
3603              case GL_TEXTURE_MAG_FILTER:
3604                *params = texture->getMagFilter();
3605                break;
3606              case GL_TEXTURE_MIN_FILTER:
3607                *params = texture->getMinFilter();
3608                break;
3609              case GL_TEXTURE_WRAP_S:
3610                *params = texture->getWrapS();
3611                break;
3612              case GL_TEXTURE_WRAP_T:
3613                *params = texture->getWrapT();
3614                break;
3615              case GL_TEXTURE_WRAP_R:
3616                if (context->getClientVersion() < 3)
3617                {
3618                    return gl::error(GL_INVALID_ENUM);
3619                }
3620                *params = texture->getWrapR();
3621                break;
3622              case GL_TEXTURE_IMMUTABLE_FORMAT:
3623                // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
3624                *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
3625                break;
3626              case GL_TEXTURE_IMMUTABLE_LEVELS:
3627                if (context->getClientVersion() < 3)
3628                {
3629                    return gl::error(GL_INVALID_ENUM);
3630                }
3631                *params = texture->immutableLevelCount();
3632                break;
3633              case GL_TEXTURE_USAGE_ANGLE:
3634                *params = texture->getUsage();
3635                break;
3636              case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3637                if (!context->supportsTextureFilterAnisotropy())
3638                {
3639                    return gl::error(GL_INVALID_ENUM);
3640                }
3641                *params = (GLint)texture->getMaxAnisotropy();
3642                break;
3643              case GL_TEXTURE_SWIZZLE_R:
3644                if (context->getClientVersion() < 3)
3645                {
3646                    return gl::error(GL_INVALID_ENUM);
3647                }
3648                *params = texture->getSwizzleRed();
3649                break;
3650              case GL_TEXTURE_SWIZZLE_G:
3651                if (context->getClientVersion() < 3)
3652                {
3653                    return gl::error(GL_INVALID_ENUM);
3654                }
3655                *params = texture->getSwizzleGreen();
3656                break;
3657              case GL_TEXTURE_SWIZZLE_B:
3658                if (context->getClientVersion() < 3)
3659                {
3660                    return gl::error(GL_INVALID_ENUM);
3661                }
3662                *params = texture->getSwizzleBlue();
3663                break;
3664              case GL_TEXTURE_SWIZZLE_A:
3665                if (context->getClientVersion() < 3)
3666                {
3667                    return gl::error(GL_INVALID_ENUM);
3668                }
3669                *params = texture->getSwizzleAlpha();
3670                break;
3671              case GL_TEXTURE_BASE_LEVEL:
3672                if (context->getClientVersion() < 3)
3673                {
3674                    return gl::error(GL_INVALID_ENUM);
3675                }
3676                *params = texture->getBaseLevel();
3677                break;
3678              case GL_TEXTURE_MAX_LEVEL:
3679                if (context->getClientVersion() < 3)
3680                {
3681                    return gl::error(GL_INVALID_ENUM);
3682                }
3683                *params = texture->getMaxLevel();
3684                break;
3685              case GL_TEXTURE_MIN_LOD:
3686                if (context->getClientVersion() < 3)
3687                {
3688                    return gl::error(GL_INVALID_ENUM);
3689                }
3690                *params = (GLint)texture->getMinLod();
3691                break;
3692              case GL_TEXTURE_MAX_LOD:
3693                if (context->getClientVersion() < 3)
3694                {
3695                    return gl::error(GL_INVALID_ENUM);
3696                }
3697                *params = (GLint)texture->getMaxLod();
3698                break;
3699              default:
3700                return gl::error(GL_INVALID_ENUM);
3701            }
3702        }
3703    }
3704    catch (...)
3705    {
3706        return gl::error(GL_OUT_OF_MEMORY);
3707    }
3708}
3709
3710void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3711{
3712    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
3713          program, location, bufSize, params);
3714
3715    try
3716    {
3717        if (bufSize < 0)
3718        {
3719            return gl::error(GL_INVALID_VALUE);
3720        }
3721
3722        gl::Context *context = gl::getNonLostContext();
3723
3724        if (context)
3725        {
3726            if (program == 0)
3727            {
3728                return gl::error(GL_INVALID_VALUE);
3729            }
3730
3731            gl::Program *programObject = context->getProgram(program);
3732
3733            if (!programObject || !programObject->isLinked())
3734            {
3735                return gl::error(GL_INVALID_OPERATION);
3736            }
3737
3738            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
3739            if (!programBinary)
3740            {
3741                return gl::error(GL_INVALID_OPERATION);
3742            }
3743
3744            if (!programBinary->getUniformfv(location, &bufSize, params))
3745            {
3746                return gl::error(GL_INVALID_OPERATION);
3747            }
3748        }
3749    }
3750    catch (...)
3751    {
3752        return gl::error(GL_OUT_OF_MEMORY);
3753    }
3754}
3755
3756void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params)
3757{
3758    EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
3759
3760    try
3761    {
3762        gl::Context *context = gl::getNonLostContext();
3763
3764        if (context)
3765        {
3766            if (program == 0)
3767            {
3768                return gl::error(GL_INVALID_VALUE);
3769            }
3770
3771            gl::Program *programObject = context->getProgram(program);
3772
3773            if (!programObject || !programObject->isLinked())
3774            {
3775                return gl::error(GL_INVALID_OPERATION);
3776            }
3777
3778            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
3779            if (!programBinary)
3780            {
3781                return gl::error(GL_INVALID_OPERATION);
3782            }
3783
3784            if (!programBinary->getUniformfv(location, NULL, params))
3785            {
3786                return gl::error(GL_INVALID_OPERATION);
3787            }
3788        }
3789    }
3790    catch (...)
3791    {
3792        return gl::error(GL_OUT_OF_MEMORY);
3793    }
3794}
3795
3796void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3797{
3798    EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
3799          program, location, bufSize, params);
3800
3801    try
3802    {
3803        if (bufSize < 0)
3804        {
3805            return gl::error(GL_INVALID_VALUE);
3806        }
3807
3808        gl::Context *context = gl::getNonLostContext();
3809
3810        if (context)
3811        {
3812            if (program == 0)
3813            {
3814                return gl::error(GL_INVALID_VALUE);
3815            }
3816
3817            gl::Program *programObject = context->getProgram(program);
3818
3819            if (!programObject || !programObject->isLinked())
3820            {
3821                return gl::error(GL_INVALID_OPERATION);
3822            }
3823
3824            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
3825            if (!programBinary)
3826            {
3827                return gl::error(GL_INVALID_OPERATION);
3828            }
3829
3830            if (!programBinary->getUniformiv(location, &bufSize, params))
3831            {
3832                return gl::error(GL_INVALID_OPERATION);
3833            }
3834        }
3835    }
3836    catch (...)
3837    {
3838        return gl::error(GL_OUT_OF_MEMORY);
3839    }
3840}
3841
3842void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params)
3843{
3844    EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
3845
3846    try
3847    {
3848        gl::Context *context = gl::getNonLostContext();
3849
3850        if (context)
3851        {
3852            if (program == 0)
3853            {
3854                return gl::error(GL_INVALID_VALUE);
3855            }
3856
3857            gl::Program *programObject = context->getProgram(program);
3858
3859            if (!programObject || !programObject->isLinked())
3860            {
3861                return gl::error(GL_INVALID_OPERATION);
3862            }
3863
3864            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
3865            if (!programBinary)
3866            {
3867                return gl::error(GL_INVALID_OPERATION);
3868            }
3869
3870            if (!programBinary->getUniformiv(location, NULL, params))
3871            {
3872                return gl::error(GL_INVALID_OPERATION);
3873            }
3874        }
3875    }
3876    catch (...)
3877    {
3878        return gl::error(GL_OUT_OF_MEMORY);
3879    }
3880}
3881
3882int __stdcall glGetUniformLocation(GLuint program, const GLchar* name)
3883{
3884    EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
3885
3886    try
3887    {
3888        gl::Context *context = gl::getNonLostContext();
3889
3890        if (strstr(name, "gl_") == name)
3891        {
3892            return -1;
3893        }
3894
3895        if (context)
3896        {
3897            gl::Program *programObject = context->getProgram(program);
3898
3899            if (!programObject)
3900            {
3901                if (context->getShader(program))
3902                {
3903                    return gl::error(GL_INVALID_OPERATION, -1);
3904                }
3905                else
3906                {
3907                    return gl::error(GL_INVALID_VALUE, -1);
3908                }
3909            }
3910
3911            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
3912            if (!programObject->isLinked() || !programBinary)
3913            {
3914                return gl::error(GL_INVALID_OPERATION, -1);
3915            }
3916
3917            return programBinary->getUniformLocation(name);
3918        }
3919    }
3920    catch (...)
3921    {
3922        return gl::error(GL_OUT_OF_MEMORY, -1);
3923    }
3924
3925    return -1;
3926}
3927
3928void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3929{
3930    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
3931
3932    try
3933    {
3934        gl::Context *context = gl::getNonLostContext();
3935
3936        if (context)
3937        {
3938            if (index >= gl::MAX_VERTEX_ATTRIBS)
3939            {
3940                return gl::error(GL_INVALID_VALUE);
3941            }
3942
3943            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
3944
3945            if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion()))
3946            {
3947                return;
3948            }
3949
3950            if (pname == GL_CURRENT_VERTEX_ATTRIB)
3951            {
3952                const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
3953                for (int i = 0; i < 4; ++i)
3954                {
3955                    params[i] = currentValueData.FloatValues[i];
3956                }
3957            }
3958            else
3959            {
3960                *params = attribState.querySingleParameter<GLfloat>(pname);
3961            }
3962        }
3963    }
3964    catch (...)
3965    {
3966        return gl::error(GL_OUT_OF_MEMORY);
3967    }
3968}
3969
3970void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3971{
3972    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
3973
3974    try
3975    {
3976        gl::Context *context = gl::getNonLostContext();
3977
3978        if (context)
3979        {
3980            if (index >= gl::MAX_VERTEX_ATTRIBS)
3981            {
3982                return gl::error(GL_INVALID_VALUE);
3983            }
3984
3985            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
3986
3987            if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion()))
3988            {
3989                return;
3990            }
3991
3992            if (pname == GL_CURRENT_VERTEX_ATTRIB)
3993            {
3994                const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
3995                for (int i = 0; i < 4; ++i)
3996                {
3997                    float currentValue = currentValueData.FloatValues[i];
3998                    params[i] = gl::iround<GLint>(currentValue);
3999                }
4000            }
4001            else
4002            {
4003                *params = attribState.querySingleParameter<GLint>(pname);
4004            }
4005        }
4006    }
4007    catch (...)
4008    {
4009        return gl::error(GL_OUT_OF_MEMORY);
4010    }
4011}
4012
4013void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4014{
4015    EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
4016
4017    try
4018    {
4019        gl::Context *context = gl::getNonLostContext();
4020
4021        if (context)
4022        {
4023            if (index >= gl::MAX_VERTEX_ATTRIBS)
4024            {
4025                return gl::error(GL_INVALID_VALUE);
4026            }
4027
4028            if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4029            {
4030                return gl::error(GL_INVALID_ENUM);
4031            }
4032
4033            *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4034        }
4035    }
4036    catch (...)
4037    {
4038        return gl::error(GL_OUT_OF_MEMORY);
4039    }
4040}
4041
4042void __stdcall glHint(GLenum target, GLenum mode)
4043{
4044    EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4045
4046    try
4047    {
4048        switch (mode)
4049        {
4050          case GL_FASTEST:
4051          case GL_NICEST:
4052          case GL_DONT_CARE:
4053            break;
4054          default:
4055            return gl::error(GL_INVALID_ENUM);
4056        }
4057
4058        gl::Context *context = gl::getNonLostContext();
4059        switch (target)
4060        {
4061          case GL_GENERATE_MIPMAP_HINT:
4062            if (context) context->setGenerateMipmapHint(mode);
4063            break;
4064          case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4065            if (context) context->setFragmentShaderDerivativeHint(mode);
4066            break;
4067          default:
4068            return gl::error(GL_INVALID_ENUM);
4069        }
4070    }
4071    catch (...)
4072    {
4073        return gl::error(GL_OUT_OF_MEMORY);
4074    }
4075}
4076
4077GLboolean __stdcall glIsBuffer(GLuint buffer)
4078{
4079    EVENT("(GLuint buffer = %d)", buffer);
4080
4081    try
4082    {
4083        gl::Context *context = gl::getNonLostContext();
4084
4085        if (context && buffer)
4086        {
4087            gl::Buffer *bufferObject = context->getBuffer(buffer);
4088
4089            if (bufferObject)
4090            {
4091                return GL_TRUE;
4092            }
4093        }
4094    }
4095    catch (...)
4096    {
4097        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4098    }
4099
4100    return GL_FALSE;
4101}
4102
4103GLboolean __stdcall glIsEnabled(GLenum cap)
4104{
4105    EVENT("(GLenum cap = 0x%X)", cap);
4106
4107    try
4108    {
4109        gl::Context *context = gl::getNonLostContext();
4110
4111        if (context)
4112        {
4113            if (!ValidCap(context, cap))
4114            {
4115                return gl::error(GL_INVALID_ENUM, false);
4116            }
4117
4118            return context->getCap(cap);
4119        }
4120    }
4121    catch (...)
4122    {
4123        return gl::error(GL_OUT_OF_MEMORY, false);
4124    }
4125
4126    return false;
4127}
4128
4129GLboolean __stdcall glIsFenceNV(GLuint fence)
4130{
4131    EVENT("(GLuint fence = %d)", fence);
4132
4133    try
4134    {
4135        gl::Context *context = gl::getNonLostContext();
4136
4137        if (context)
4138        {
4139            gl::FenceNV *fenceObject = context->getFenceNV(fence);
4140
4141            if (fenceObject == NULL)
4142            {
4143                return GL_FALSE;
4144            }
4145
4146            return fenceObject->isFence();
4147        }
4148    }
4149    catch (...)
4150    {
4151        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4152    }
4153
4154    return GL_FALSE;
4155}
4156
4157GLboolean __stdcall glIsFramebuffer(GLuint framebuffer)
4158{
4159    EVENT("(GLuint framebuffer = %d)", framebuffer);
4160
4161    try
4162    {
4163        gl::Context *context = gl::getNonLostContext();
4164
4165        if (context && framebuffer)
4166        {
4167            gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4168
4169            if (framebufferObject)
4170            {
4171                return GL_TRUE;
4172            }
4173        }
4174    }
4175    catch (...)
4176    {
4177        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4178    }
4179
4180    return GL_FALSE;
4181}
4182
4183GLboolean __stdcall glIsProgram(GLuint program)
4184{
4185    EVENT("(GLuint program = %d)", program);
4186
4187    try
4188    {
4189        gl::Context *context = gl::getNonLostContext();
4190
4191        if (context && program)
4192        {
4193            gl::Program *programObject = context->getProgram(program);
4194
4195            if (programObject)
4196            {
4197                return GL_TRUE;
4198            }
4199        }
4200    }
4201    catch (...)
4202    {
4203        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4204    }
4205
4206    return GL_FALSE;
4207}
4208
4209GLboolean __stdcall glIsQueryEXT(GLuint id)
4210{
4211    EVENT("(GLuint id = %d)", id);
4212
4213    try
4214    {
4215        gl::Context *context = gl::getNonLostContext();
4216
4217        if (context)
4218        {
4219            return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
4220        }
4221    }
4222    catch (...)
4223    {
4224        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4225    }
4226
4227    return GL_FALSE;
4228}
4229
4230GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer)
4231{
4232    EVENT("(GLuint renderbuffer = %d)", renderbuffer);
4233
4234    try
4235    {
4236        gl::Context *context = gl::getNonLostContext();
4237
4238        if (context && renderbuffer)
4239        {
4240            gl::FramebufferAttachment *renderbufferObject = context->getRenderbuffer(renderbuffer);
4241
4242            if (renderbufferObject)
4243            {
4244                return GL_TRUE;
4245            }
4246        }
4247    }
4248    catch (...)
4249    {
4250        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4251    }
4252
4253    return GL_FALSE;
4254}
4255
4256GLboolean __stdcall glIsShader(GLuint shader)
4257{
4258    EVENT("(GLuint shader = %d)", shader);
4259
4260    try
4261    {
4262        gl::Context *context = gl::getNonLostContext();
4263
4264        if (context && shader)
4265        {
4266            gl::Shader *shaderObject = context->getShader(shader);
4267
4268            if (shaderObject)
4269            {
4270                return GL_TRUE;
4271            }
4272        }
4273    }
4274    catch (...)
4275    {
4276        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4277    }
4278
4279    return GL_FALSE;
4280}
4281
4282GLboolean __stdcall glIsTexture(GLuint texture)
4283{
4284    EVENT("(GLuint texture = %d)", texture);
4285
4286    try
4287    {
4288        gl::Context *context = gl::getNonLostContext();
4289
4290        if (context && texture)
4291        {
4292            gl::Texture *textureObject = context->getTexture(texture);
4293
4294            if (textureObject)
4295            {
4296                return GL_TRUE;
4297            }
4298        }
4299    }
4300    catch (...)
4301    {
4302        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
4303    }
4304
4305    return GL_FALSE;
4306}
4307
4308void __stdcall glLineWidth(GLfloat width)
4309{
4310    EVENT("(GLfloat width = %f)", width);
4311
4312    try
4313    {
4314        if (width <= 0.0f)
4315        {
4316            return gl::error(GL_INVALID_VALUE);
4317        }
4318
4319        gl::Context *context = gl::getNonLostContext();
4320
4321        if (context)
4322        {
4323            context->setLineWidth(width);
4324        }
4325    }
4326    catch (...)
4327    {
4328        return gl::error(GL_OUT_OF_MEMORY);
4329    }
4330}
4331
4332void __stdcall glLinkProgram(GLuint program)
4333{
4334    EVENT("(GLuint program = %d)", program);
4335
4336    try
4337    {
4338        gl::Context *context = gl::getNonLostContext();
4339
4340        if (context)
4341        {
4342            gl::Program *programObject = context->getProgram(program);
4343
4344            if (!programObject)
4345            {
4346                if (context->getShader(program))
4347                {
4348                    return gl::error(GL_INVALID_OPERATION);
4349                }
4350                else
4351                {
4352                    return gl::error(GL_INVALID_VALUE);
4353                }
4354            }
4355
4356            context->linkProgram(program);
4357        }
4358    }
4359    catch (...)
4360    {
4361        return gl::error(GL_OUT_OF_MEMORY);
4362    }
4363}
4364
4365void __stdcall glPixelStorei(GLenum pname, GLint param)
4366{
4367    EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4368
4369    try
4370    {
4371        gl::Context *context = gl::getNonLostContext();
4372
4373        if (context)
4374        {
4375            switch (pname)
4376            {
4377              case GL_UNPACK_ALIGNMENT:
4378                if (param != 1 && param != 2 && param != 4 && param != 8)
4379                {
4380                    return gl::error(GL_INVALID_VALUE);
4381                }
4382
4383                context->setUnpackAlignment(param);
4384                break;
4385
4386              case GL_PACK_ALIGNMENT:
4387                if (param != 1 && param != 2 && param != 4 && param != 8)
4388                {
4389                    return gl::error(GL_INVALID_VALUE);
4390                }
4391
4392                context->setPackAlignment(param);
4393                break;
4394
4395              case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4396                context->setPackReverseRowOrder(param != 0);
4397                break;
4398
4399              case GL_UNPACK_IMAGE_HEIGHT:
4400              case GL_UNPACK_SKIP_IMAGES:
4401              case GL_UNPACK_ROW_LENGTH:
4402              case GL_UNPACK_SKIP_ROWS:
4403              case GL_UNPACK_SKIP_PIXELS:
4404              case GL_PACK_ROW_LENGTH:
4405              case GL_PACK_SKIP_ROWS:
4406              case GL_PACK_SKIP_PIXELS:
4407                if (context->getClientVersion() < 3)
4408                {
4409                    return gl::error(GL_INVALID_ENUM);
4410                }
4411                UNIMPLEMENTED();
4412                break;
4413
4414              default:
4415                return gl::error(GL_INVALID_ENUM);
4416            }
4417        }
4418    }
4419    catch (...)
4420    {
4421        return gl::error(GL_OUT_OF_MEMORY);
4422    }
4423}
4424
4425void __stdcall glPolygonOffset(GLfloat factor, GLfloat units)
4426{
4427    EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4428
4429    try
4430    {
4431        gl::Context *context = gl::getNonLostContext();
4432
4433        if (context)
4434        {
4435            context->setPolygonOffsetParams(factor, units);
4436        }
4437    }
4438    catch (...)
4439    {
4440        return gl::error(GL_OUT_OF_MEMORY);
4441    }
4442}
4443
4444void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4445                                GLenum format, GLenum type, GLsizei bufSize,
4446                                GLvoid *data)
4447{
4448    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4449          "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
4450          x, y, width, height, format, type, bufSize, data);
4451
4452    try
4453    {
4454        if (width < 0 || height < 0 || bufSize < 0)
4455        {
4456            return gl::error(GL_INVALID_VALUE);
4457        }
4458
4459        gl::Context *context = gl::getNonLostContext();
4460
4461        if (context)
4462        {
4463            if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
4464                                                  format, type, &bufSize, data))
4465            {
4466                return;
4467            }
4468
4469            context->readPixels(x, y, width, height, format, type, &bufSize, data);
4470        }
4471    }
4472    catch (...)
4473    {
4474        return gl::error(GL_OUT_OF_MEMORY);
4475    }
4476}
4477
4478void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
4479                            GLenum format, GLenum type, GLvoid* pixels)
4480{
4481    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4482          "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
4483          x, y, width, height, format, type,  pixels);
4484
4485    try
4486    {
4487        if (width < 0 || height < 0)
4488        {
4489            return gl::error(GL_INVALID_VALUE);
4490        }
4491
4492        gl::Context *context = gl::getNonLostContext();
4493
4494        if (context)
4495        {
4496            if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
4497                                                  format, type, NULL, pixels))
4498            {
4499                return;
4500            }
4501
4502            context->readPixels(x, y, width, height, format, type, NULL, pixels);
4503        }
4504    }
4505    catch (...)
4506    {
4507        return gl::error(GL_OUT_OF_MEMORY);
4508    }
4509}
4510
4511void __stdcall glReleaseShaderCompiler(void)
4512{
4513    EVENT("()");
4514
4515    try
4516    {
4517        gl::Shader::releaseCompiler();
4518    }
4519    catch (...)
4520    {
4521        return gl::error(GL_OUT_OF_MEMORY);
4522    }
4523}
4524
4525void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4526{
4527    EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4528          target, samples, internalformat, width, height);
4529
4530    try
4531    {
4532        gl::Context *context = gl::getNonLostContext();
4533
4534        if (context)
4535        {
4536            if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
4537                                                       width, height, true))
4538            {
4539                return;
4540            }
4541
4542            context->setRenderbufferStorage(width, height, internalformat, samples);
4543        }
4544    }
4545    catch (...)
4546    {
4547        return gl::error(GL_OUT_OF_MEMORY);
4548    }
4549}
4550
4551void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4552{
4553    glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
4554}
4555
4556void __stdcall glSampleCoverage(GLclampf value, GLboolean invert)
4557{
4558    EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
4559
4560    try
4561    {
4562        gl::Context* context = gl::getNonLostContext();
4563
4564        if (context)
4565        {
4566            context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
4567        }
4568    }
4569    catch (...)
4570    {
4571        return gl::error(GL_OUT_OF_MEMORY);
4572    }
4573}
4574
4575void __stdcall glSetFenceNV(GLuint fence, GLenum condition)
4576{
4577    EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4578
4579    try
4580    {
4581        if (condition != GL_ALL_COMPLETED_NV)
4582        {
4583            return gl::error(GL_INVALID_ENUM);
4584        }
4585
4586        gl::Context *context = gl::getNonLostContext();
4587
4588        if (context)
4589        {
4590            gl::FenceNV *fenceObject = context->getFenceNV(fence);
4591
4592            if (fenceObject == NULL)
4593            {
4594                return gl::error(GL_INVALID_OPERATION);
4595            }
4596
4597            fenceObject->setFence(condition);
4598        }
4599    }
4600    catch (...)
4601    {
4602        return gl::error(GL_OUT_OF_MEMORY);
4603    }
4604}
4605
4606void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
4607{
4608    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4609
4610    try
4611    {
4612        if (width < 0 || height < 0)
4613        {
4614            return gl::error(GL_INVALID_VALUE);
4615        }
4616
4617        gl::Context* context = gl::getNonLostContext();
4618
4619        if (context)
4620        {
4621            context->setScissorParams(x, y, width, height);
4622        }
4623    }
4624    catch (...)
4625    {
4626        return gl::error(GL_OUT_OF_MEMORY);
4627    }
4628}
4629
4630void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4631{
4632    EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
4633          "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
4634          n, shaders, binaryformat, binary, length);
4635
4636    try
4637    {
4638        // No binary shader formats are supported.
4639        return gl::error(GL_INVALID_ENUM);
4640    }
4641    catch (...)
4642    {
4643        return gl::error(GL_OUT_OF_MEMORY);
4644    }
4645}
4646
4647void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
4648{
4649    EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
4650          shader, count, string, length);
4651
4652    try
4653    {
4654        if (count < 0)
4655        {
4656            return gl::error(GL_INVALID_VALUE);
4657        }
4658
4659        gl::Context *context = gl::getNonLostContext();
4660
4661        if (context)
4662        {
4663            gl::Shader *shaderObject = context->getShader(shader);
4664
4665            if (!shaderObject)
4666            {
4667                if (context->getProgram(shader))
4668                {
4669                    return gl::error(GL_INVALID_OPERATION);
4670                }
4671                else
4672                {
4673                    return gl::error(GL_INVALID_VALUE);
4674                }
4675            }
4676
4677            shaderObject->setSource(count, string, length);
4678        }
4679    }
4680    catch (...)
4681    {
4682        return gl::error(GL_OUT_OF_MEMORY);
4683    }
4684}
4685
4686void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask)
4687{
4688    glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4689}
4690
4691void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4692{
4693    EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4694
4695    try
4696    {
4697        switch (face)
4698        {
4699          case GL_FRONT:
4700          case GL_BACK:
4701          case GL_FRONT_AND_BACK:
4702            break;
4703          default:
4704            return gl::error(GL_INVALID_ENUM);
4705        }
4706
4707        switch (func)
4708        {
4709          case GL_NEVER:
4710          case GL_ALWAYS:
4711          case GL_LESS:
4712          case GL_LEQUAL:
4713          case GL_EQUAL:
4714          case GL_GEQUAL:
4715          case GL_GREATER:
4716          case GL_NOTEQUAL:
4717            break;
4718          default:
4719            return gl::error(GL_INVALID_ENUM);
4720        }
4721
4722        gl::Context *context = gl::getNonLostContext();
4723
4724        if (context)
4725        {
4726            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
4727            {
4728                context->setStencilParams(func, ref, mask);
4729            }
4730
4731            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
4732            {
4733                context->setStencilBackParams(func, ref, mask);
4734            }
4735        }
4736    }
4737    catch (...)
4738    {
4739        return gl::error(GL_OUT_OF_MEMORY);
4740    }
4741}
4742
4743void __stdcall glStencilMask(GLuint mask)
4744{
4745    glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4746}
4747
4748void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask)
4749{
4750    EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4751
4752    try
4753    {
4754        switch (face)
4755        {
4756          case GL_FRONT:
4757          case GL_BACK:
4758          case GL_FRONT_AND_BACK:
4759            break;
4760          default:
4761            return gl::error(GL_INVALID_ENUM);
4762        }
4763
4764        gl::Context *context = gl::getNonLostContext();
4765
4766        if (context)
4767        {
4768            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
4769            {
4770                context->setStencilWritemask(mask);
4771            }
4772
4773            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
4774            {
4775                context->setStencilBackWritemask(mask);
4776            }
4777        }
4778    }
4779    catch (...)
4780    {
4781        return gl::error(GL_OUT_OF_MEMORY);
4782    }
4783}
4784
4785void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4786{
4787    glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4788}
4789
4790void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4791{
4792    EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4793          face, fail, zfail, zpass);
4794
4795    try
4796    {
4797        switch (face)
4798        {
4799          case GL_FRONT:
4800          case GL_BACK:
4801          case GL_FRONT_AND_BACK:
4802            break;
4803          default:
4804            return gl::error(GL_INVALID_ENUM);
4805        }
4806
4807        switch (fail)
4808        {
4809          case GL_ZERO:
4810          case GL_KEEP:
4811          case GL_REPLACE:
4812          case GL_INCR:
4813          case GL_DECR:
4814          case GL_INVERT:
4815          case GL_INCR_WRAP:
4816          case GL_DECR_WRAP:
4817            break;
4818          default:
4819            return gl::error(GL_INVALID_ENUM);
4820        }
4821
4822        switch (zfail)
4823        {
4824          case GL_ZERO:
4825          case GL_KEEP:
4826          case GL_REPLACE:
4827          case GL_INCR:
4828          case GL_DECR:
4829          case GL_INVERT:
4830          case GL_INCR_WRAP:
4831          case GL_DECR_WRAP:
4832            break;
4833          default:
4834            return gl::error(GL_INVALID_ENUM);
4835        }
4836
4837        switch (zpass)
4838        {
4839          case GL_ZERO:
4840          case GL_KEEP:
4841          case GL_REPLACE:
4842          case GL_INCR:
4843          case GL_DECR:
4844          case GL_INVERT:
4845          case GL_INCR_WRAP:
4846          case GL_DECR_WRAP:
4847            break;
4848          default:
4849            return gl::error(GL_INVALID_ENUM);
4850        }
4851
4852        gl::Context *context = gl::getNonLostContext();
4853
4854        if (context)
4855        {
4856            if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
4857            {
4858                context->setStencilOperations(fail, zfail, zpass);
4859            }
4860
4861            if (face == GL_BACK || face == GL_FRONT_AND_BACK)
4862            {
4863                context->setStencilBackOperations(fail, zfail, zpass);
4864            }
4865        }
4866    }
4867    catch (...)
4868    {
4869        return gl::error(GL_OUT_OF_MEMORY);
4870    }
4871}
4872
4873GLboolean __stdcall glTestFenceNV(GLuint fence)
4874{
4875    EVENT("(GLuint fence = %d)", fence);
4876
4877    try
4878    {
4879        gl::Context *context = gl::getNonLostContext();
4880
4881        if (context)
4882        {
4883            gl::FenceNV *fenceObject = context->getFenceNV(fence);
4884
4885            if (fenceObject == NULL)
4886            {
4887                return gl::error(GL_INVALID_OPERATION, GL_TRUE);
4888            }
4889
4890            if (fenceObject->isFence() != GL_TRUE)
4891            {
4892                return gl::error(GL_INVALID_OPERATION, GL_TRUE);
4893            }
4894
4895            return fenceObject->testFence();
4896        }
4897    }
4898    catch (...)
4899    {
4900        gl::error(GL_OUT_OF_MEMORY);
4901    }
4902
4903    return GL_TRUE;
4904}
4905
4906void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4907                            GLint border, GLenum format, GLenum type, const GLvoid* pixels)
4908{
4909    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
4910          "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
4911          target, level, internalformat, width, height, border, format, type, pixels);
4912
4913    try
4914    {
4915        gl::Context *context = gl::getNonLostContext();
4916
4917        if (context)
4918        {
4919            if (context->getClientVersion() < 3 &&
4920                !ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
4921                                               0, 0, width, height, border, format, type, pixels))
4922            {
4923                return;
4924            }
4925
4926            if (context->getClientVersion() >= 3 &&
4927                !ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
4928                                               0, 0, 0, width, height, 1, border, format, type, pixels))
4929            {
4930                return;
4931            }
4932
4933            switch (target)
4934            {
4935              case GL_TEXTURE_2D:
4936                {
4937                    gl::Texture2D *texture = context->getTexture2D();
4938                    texture->setImage(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4939                }
4940                break;
4941              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4942                {
4943                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4944                    texture->setImagePosX(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4945                }
4946                break;
4947              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4948                {
4949                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4950                    texture->setImageNegX(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4951                }
4952                break;
4953              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4954                {
4955                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4956                    texture->setImagePosY(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4957                }
4958                break;
4959              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4960                {
4961                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4962                    texture->setImageNegY(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4963                }
4964                break;
4965              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4966                {
4967                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4968                    texture->setImagePosZ(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4969                }
4970                break;
4971              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4972                {
4973                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
4974                    texture->setImageNegZ(level, width, height, internalformat, format, type, context->getUnpackState(), pixels);
4975                }
4976                break;
4977              default: UNREACHABLE();
4978            }
4979        }
4980    }
4981    catch (...)
4982    {
4983        return gl::error(GL_OUT_OF_MEMORY);
4984    }
4985}
4986
4987void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param)
4988{
4989    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
4990
4991    try
4992    {
4993        gl::Context *context = gl::getNonLostContext();
4994
4995        if (context)
4996        {
4997            if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
4998            {
4999                return;
5000            }
5001
5002            gl::Texture *texture = context->getTargetTexture(target);
5003
5004            if (!texture)
5005            {
5006                return gl::error(GL_INVALID_ENUM);
5007            }
5008
5009            switch (pname)
5010            {
5011              case GL_TEXTURE_WRAP_S:               texture->setWrapS(gl::uiround<GLenum>(param));       break;
5012              case GL_TEXTURE_WRAP_T:               texture->setWrapT(gl::uiround<GLenum>(param));       break;
5013              case GL_TEXTURE_WRAP_R:               texture->setWrapR(gl::uiround<GLenum>(param));       break;
5014              case GL_TEXTURE_MIN_FILTER:           texture->setMinFilter(gl::uiround<GLenum>(param));   break;
5015              case GL_TEXTURE_MAG_FILTER:           texture->setMagFilter(gl::uiround<GLenum>(param));   break;
5016              case GL_TEXTURE_USAGE_ANGLE:          texture->setUsage(gl::uiround<GLenum>(param));       break;
5017              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->setMaxAnisotropy(param, context->getTextureMaxAnisotropy()); break;
5018              case GL_TEXTURE_COMPARE_MODE:         texture->setCompareMode(gl::uiround<GLenum>(param)); break;
5019              case GL_TEXTURE_COMPARE_FUNC:         texture->setCompareFunc(gl::uiround<GLenum>(param)); break;
5020              case GL_TEXTURE_SWIZZLE_R:            texture->setSwizzleRed(gl::uiround<GLenum>(param));   break;
5021              case GL_TEXTURE_SWIZZLE_G:            texture->setSwizzleGreen(gl::uiround<GLenum>(param)); break;
5022              case GL_TEXTURE_SWIZZLE_B:            texture->setSwizzleBlue(gl::uiround<GLenum>(param));  break;
5023              case GL_TEXTURE_SWIZZLE_A:            texture->setSwizzleAlpha(gl::uiround<GLenum>(param)); break;
5024              case GL_TEXTURE_BASE_LEVEL:           texture->setBaseLevel(gl::iround<GLint>(param));      break;
5025              case GL_TEXTURE_MAX_LEVEL:            texture->setMaxLevel(gl::iround<GLint>(param));       break;
5026              case GL_TEXTURE_MIN_LOD:              texture->setMinLod(param);                            break;
5027              case GL_TEXTURE_MAX_LOD:              texture->setMaxLod(param);                            break;
5028              default: UNREACHABLE(); break;
5029            }
5030        }
5031    }
5032    catch (...)
5033    {
5034        return gl::error(GL_OUT_OF_MEMORY);
5035    }
5036}
5037
5038void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5039{
5040    glTexParameterf(target, pname, (GLfloat)*params);
5041}
5042
5043void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param)
5044{
5045    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5046
5047    try
5048    {
5049        gl::Context *context = gl::getNonLostContext();
5050
5051        if (context)
5052        {
5053            if (!ValidateTexParamParameters(context, pname, param))
5054            {
5055                return;
5056            }
5057
5058            gl::Texture *texture = context->getTargetTexture(target);
5059
5060            if (!texture)
5061            {
5062                return gl::error(GL_INVALID_ENUM);
5063            }
5064
5065            switch (pname)
5066            {
5067              case GL_TEXTURE_WRAP_S:               texture->setWrapS((GLenum)param);       break;
5068              case GL_TEXTURE_WRAP_T:               texture->setWrapT((GLenum)param);       break;
5069              case GL_TEXTURE_WRAP_R:               texture->setWrapR((GLenum)param);       break;
5070              case GL_TEXTURE_MIN_FILTER:           texture->setMinFilter((GLenum)param);   break;
5071              case GL_TEXTURE_MAG_FILTER:           texture->setMagFilter((GLenum)param);   break;
5072              case GL_TEXTURE_USAGE_ANGLE:          texture->setUsage((GLenum)param);       break;
5073              case GL_TEXTURE_MAX_ANISOTROPY_EXT:   texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy()); break;
5074              case GL_TEXTURE_COMPARE_MODE:         texture->setCompareMode((GLenum)param); break;
5075              case GL_TEXTURE_COMPARE_FUNC:         texture->setCompareFunc((GLenum)param); break;
5076              case GL_TEXTURE_SWIZZLE_R:            texture->setSwizzleRed((GLenum)param);   break;
5077              case GL_TEXTURE_SWIZZLE_G:            texture->setSwizzleGreen((GLenum)param); break;
5078              case GL_TEXTURE_SWIZZLE_B:            texture->setSwizzleBlue((GLenum)param);  break;
5079              case GL_TEXTURE_SWIZZLE_A:            texture->setSwizzleAlpha((GLenum)param); break;
5080              case GL_TEXTURE_BASE_LEVEL:           texture->setBaseLevel(param);            break;
5081              case GL_TEXTURE_MAX_LEVEL:            texture->setMaxLevel(param);             break;
5082              case GL_TEXTURE_MIN_LOD:              texture->setMinLod((GLfloat)param);      break;
5083              case GL_TEXTURE_MAX_LOD:              texture->setMaxLod((GLfloat)param);      break;
5084              default: UNREACHABLE(); break;
5085            }
5086        }
5087    }
5088    catch (...)
5089    {
5090        return gl::error(GL_OUT_OF_MEMORY);
5091    }
5092}
5093
5094void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
5095{
5096    glTexParameteri(target, pname, *params);
5097}
5098
5099void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
5100{
5101    EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
5102           target, levels, internalformat, width, height);
5103
5104    try
5105    {
5106        gl::Context *context = gl::getNonLostContext();
5107
5108        if (context)
5109        {
5110            if (context->getClientVersion() < 3 &&
5111                !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height))
5112            {
5113                return;
5114            }
5115
5116            if (context->getClientVersion() >= 3 &&
5117                !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
5118            {
5119                return;
5120            }
5121
5122            switch (target)
5123            {
5124              case GL_TEXTURE_2D:
5125                {
5126                    gl::Texture2D *texture2d = context->getTexture2D();
5127                    texture2d->storage(levels, internalformat, width, height);
5128                }
5129                break;
5130
5131              case GL_TEXTURE_CUBE_MAP:
5132                {
5133                    gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
5134                    textureCube->storage(levels, internalformat, width);
5135                }
5136                break;
5137
5138              default:
5139                return gl::error(GL_INVALID_ENUM);
5140            }
5141        }
5142    }
5143    catch (...)
5144    {
5145        return gl::error(GL_OUT_OF_MEMORY);
5146    }
5147}
5148
5149void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
5150                               GLenum format, GLenum type, const GLvoid* pixels)
5151{
5152    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5153          "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
5154          "const GLvoid* pixels = 0x%0.8p)",
5155           target, level, xoffset, yoffset, width, height, format, type, pixels);
5156
5157    try
5158    {
5159        gl::Context *context = gl::getNonLostContext();
5160
5161        if (context)
5162        {
5163            if (context->getClientVersion() < 3 &&
5164                !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true,
5165                                               xoffset, yoffset, width, height, 0, format, type, pixels))
5166            {
5167                return;
5168            }
5169
5170            if (context->getClientVersion() >= 3 &&
5171                !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
5172                                               xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels))
5173            {
5174                return;
5175            }
5176
5177            // Zero sized uploads are valid but no-ops
5178            if (width == 0 || height == 0)
5179            {
5180                return;
5181            }
5182
5183            switch (target)
5184            {
5185              case GL_TEXTURE_2D:
5186                {
5187                    gl::Texture2D *texture = context->getTexture2D();
5188                    texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackState(), pixels);
5189                }
5190                break;
5191
5192              case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5193              case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5194              case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5195              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5196              case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5197              case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5198                {
5199                    gl::TextureCubeMap *texture = context->getTextureCubeMap();
5200                    texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackState(), pixels);
5201                }
5202                break;
5203
5204              default:
5205                UNREACHABLE();
5206            }
5207        }
5208    }
5209    catch (...)
5210    {
5211        return gl::error(GL_OUT_OF_MEMORY);
5212    }
5213}
5214
5215void __stdcall glUniform1f(GLint location, GLfloat x)
5216{
5217    glUniform1fv(location, 1, &x);
5218}
5219
5220void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
5221{
5222    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5223
5224    try
5225    {
5226        gl::Context *context = gl::getNonLostContext();
5227
5228        if (context)
5229        {
5230            if (!ValidateUniform(context, GL_FLOAT, location, count))
5231            {
5232                return;
5233            }
5234
5235            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5236            programBinary->setUniform1fv(location, count, v);
5237        }
5238    }
5239    catch (...)
5240    {
5241        return gl::error(GL_OUT_OF_MEMORY);
5242    }
5243}
5244
5245void __stdcall glUniform1i(GLint location, GLint x)
5246{
5247    glUniform1iv(location, 1, &x);
5248}
5249
5250void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v)
5251{
5252    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5253
5254    try
5255    {
5256        gl::Context *context = gl::getNonLostContext();
5257
5258        if (context)
5259        {
5260            if (!ValidateUniform(context, GL_INT, location, count))
5261            {
5262                return;
5263            }
5264
5265            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5266            programBinary->setUniform1iv(location, count, v);
5267        }
5268    }
5269    catch (...)
5270    {
5271        return gl::error(GL_OUT_OF_MEMORY);
5272    }
5273}
5274
5275void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y)
5276{
5277    GLfloat xy[2] = {x, y};
5278
5279    glUniform2fv(location, 1, xy);
5280}
5281
5282void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
5283{
5284    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5285
5286    try
5287    {
5288        gl::Context *context = gl::getNonLostContext();
5289
5290        if (context)
5291        {
5292            if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
5293            {
5294                return;
5295            }
5296
5297            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5298            programBinary->setUniform2fv(location, count, v);
5299        }
5300    }
5301    catch (...)
5302    {
5303        return gl::error(GL_OUT_OF_MEMORY);
5304    }
5305}
5306
5307void __stdcall glUniform2i(GLint location, GLint x, GLint y)
5308{
5309    GLint xy[2] = {x, y};
5310
5311    glUniform2iv(location, 1, xy);
5312}
5313
5314void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v)
5315{
5316    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5317
5318    try
5319    {
5320        gl::Context *context = gl::getNonLostContext();
5321
5322        if (context)
5323        {
5324            if (!ValidateUniform(context, GL_INT_VEC2, location, count))
5325            {
5326                return;
5327            }
5328
5329            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5330            programBinary->setUniform2iv(location, count, v);
5331        }
5332    }
5333    catch (...)
5334    {
5335        return gl::error(GL_OUT_OF_MEMORY);
5336    }
5337}
5338
5339void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5340{
5341    GLfloat xyz[3] = {x, y, z};
5342
5343    glUniform3fv(location, 1, xyz);
5344}
5345
5346void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
5347{
5348    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5349
5350    try
5351    {
5352        gl::Context *context = gl::getNonLostContext();
5353
5354        if (context)
5355        {
5356            if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
5357            {
5358                return;
5359            }
5360
5361            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5362            programBinary->setUniform3fv(location, count, v);
5363        }
5364    }
5365    catch (...)
5366    {
5367        return gl::error(GL_OUT_OF_MEMORY);
5368    }
5369}
5370
5371void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z)
5372{
5373    GLint xyz[3] = {x, y, z};
5374
5375    glUniform3iv(location, 1, xyz);
5376}
5377
5378void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v)
5379{
5380    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5381
5382    try
5383    {
5384        gl::Context *context = gl::getNonLostContext();
5385
5386        if (context)
5387        {
5388            if (!ValidateUniform(context, GL_INT_VEC3, location, count))
5389            {
5390                return;
5391            }
5392
5393            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5394            programBinary->setUniform3iv(location, count, v);
5395        }
5396    }
5397    catch (...)
5398    {
5399        return gl::error(GL_OUT_OF_MEMORY);
5400    }
5401}
5402
5403void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5404{
5405    GLfloat xyzw[4] = {x, y, z, w};
5406
5407    glUniform4fv(location, 1, xyzw);
5408}
5409
5410void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
5411{
5412    EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5413
5414    try
5415    {
5416        gl::Context *context = gl::getNonLostContext();
5417
5418        if (context)
5419        {
5420            if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
5421            {
5422                return;
5423            }
5424
5425            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5426            programBinary->setUniform4fv(location, count, v);
5427        }
5428    }
5429    catch (...)
5430    {
5431        return gl::error(GL_OUT_OF_MEMORY);
5432    }
5433}
5434
5435void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5436{
5437    GLint xyzw[4] = {x, y, z, w};
5438
5439    glUniform4iv(location, 1, xyzw);
5440}
5441
5442void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v)
5443{
5444    EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5445
5446    try
5447    {
5448        gl::Context *context = gl::getNonLostContext();
5449
5450        if (context)
5451        {
5452            if (!ValidateUniform(context, GL_INT_VEC4, location, count))
5453            {
5454                return;
5455            }
5456
5457            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5458            programBinary->setUniform4iv(location, count, v);
5459        }
5460    }
5461    catch (...)
5462    {
5463        return gl::error(GL_OUT_OF_MEMORY);
5464    }
5465}
5466
5467void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5468{
5469    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
5470          location, count, transpose, value);
5471
5472    try
5473    {
5474        gl::Context *context = gl::getNonLostContext();
5475
5476        if (context)
5477        {
5478            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
5479            {
5480                return;
5481            }
5482
5483            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5484            programBinary->setUniformMatrix2fv(location, count, transpose, value);
5485        }
5486    }
5487    catch (...)
5488    {
5489        return gl::error(GL_OUT_OF_MEMORY);
5490    }
5491}
5492
5493void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5494{
5495    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
5496          location, count, transpose, value);
5497
5498    try
5499    {
5500        gl::Context *context = gl::getNonLostContext();
5501
5502        if (context)
5503        {
5504            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
5505            {
5506                return;
5507            }
5508
5509            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5510            programBinary->setUniformMatrix3fv(location, count, transpose, value);
5511        }
5512    }
5513    catch (...)
5514    {
5515        return gl::error(GL_OUT_OF_MEMORY);
5516    }
5517}
5518
5519void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5520{
5521    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
5522          location, count, transpose, value);
5523
5524    try
5525    {
5526        gl::Context *context = gl::getNonLostContext();
5527
5528        if (context)
5529        {
5530            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
5531            {
5532                return;
5533            }
5534
5535            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
5536            programBinary->setUniformMatrix4fv(location, count, transpose, value);
5537        }
5538    }
5539    catch (...)
5540    {
5541        return gl::error(GL_OUT_OF_MEMORY);
5542    }
5543}
5544
5545void __stdcall glUseProgram(GLuint program)
5546{
5547    EVENT("(GLuint program = %d)", program);
5548
5549    try
5550    {
5551        gl::Context *context = gl::getNonLostContext();
5552
5553        if (context)
5554        {
5555            gl::Program *programObject = context->getProgram(program);
5556
5557            if (!programObject && program != 0)
5558            {
5559                if (context->getShader(program))
5560                {
5561                    return gl::error(GL_INVALID_OPERATION);
5562                }
5563                else
5564                {
5565                    return gl::error(GL_INVALID_VALUE);
5566                }
5567            }
5568
5569            if (program != 0 && !programObject->isLinked())
5570            {
5571                return gl::error(GL_INVALID_OPERATION);
5572            }
5573
5574            context->useProgram(program);
5575        }
5576    }
5577    catch (...)
5578    {
5579        return gl::error(GL_OUT_OF_MEMORY);
5580    }
5581}
5582
5583void __stdcall glValidateProgram(GLuint program)
5584{
5585    EVENT("(GLuint program = %d)", program);
5586
5587    try
5588    {
5589        gl::Context *context = gl::getNonLostContext();
5590
5591        if (context)
5592        {
5593            gl::Program *programObject = context->getProgram(program);
5594
5595            if (!programObject)
5596            {
5597                if (context->getShader(program))
5598                {
5599                    return gl::error(GL_INVALID_OPERATION);
5600                }
5601                else
5602                {
5603                    return gl::error(GL_INVALID_VALUE);
5604                }
5605            }
5606
5607            programObject->validate();
5608        }
5609    }
5610    catch (...)
5611    {
5612        return gl::error(GL_OUT_OF_MEMORY);
5613    }
5614}
5615
5616void __stdcall glVertexAttrib1f(GLuint index, GLfloat x)
5617{
5618    EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
5619
5620    try
5621    {
5622        if (index >= gl::MAX_VERTEX_ATTRIBS)
5623        {
5624            return gl::error(GL_INVALID_VALUE);
5625        }
5626
5627        gl::Context *context = gl::getNonLostContext();
5628
5629        if (context)
5630        {
5631            GLfloat vals[4] = { x, 0, 0, 1 };
5632            context->setVertexAttribf(index, vals);
5633        }
5634    }
5635    catch (...)
5636    {
5637        return gl::error(GL_OUT_OF_MEMORY);
5638    }
5639}
5640
5641void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values)
5642{
5643    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5644
5645    try
5646    {
5647        if (index >= gl::MAX_VERTEX_ATTRIBS)
5648        {
5649            return gl::error(GL_INVALID_VALUE);
5650        }
5651
5652        gl::Context *context = gl::getNonLostContext();
5653
5654        if (context)
5655        {
5656            GLfloat vals[4] = { values[0], 0, 0, 1 };
5657            context->setVertexAttribf(index, vals);
5658        }
5659    }
5660    catch (...)
5661    {
5662        return gl::error(GL_OUT_OF_MEMORY);
5663    }
5664}
5665
5666void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5667{
5668    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5669
5670    try
5671    {
5672        if (index >= gl::MAX_VERTEX_ATTRIBS)
5673        {
5674            return gl::error(GL_INVALID_VALUE);
5675        }
5676
5677        gl::Context *context = gl::getNonLostContext();
5678
5679        if (context)
5680        {
5681            GLfloat vals[4] = { x, y, 0, 1 };
5682            context->setVertexAttribf(index, vals);
5683        }
5684    }
5685    catch (...)
5686    {
5687        return gl::error(GL_OUT_OF_MEMORY);
5688    }
5689}
5690
5691void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values)
5692{
5693    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5694
5695    try
5696    {
5697        if (index >= gl::MAX_VERTEX_ATTRIBS)
5698        {
5699            return gl::error(GL_INVALID_VALUE);
5700        }
5701
5702        gl::Context *context = gl::getNonLostContext();
5703
5704        if (context)
5705        {
5706            GLfloat vals[4] = { values[0], values[1], 0, 1 };
5707            context->setVertexAttribf(index, vals);
5708        }
5709    }
5710    catch (...)
5711    {
5712        return gl::error(GL_OUT_OF_MEMORY);
5713    }
5714}
5715
5716void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5717{
5718    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5719
5720    try
5721    {
5722        if (index >= gl::MAX_VERTEX_ATTRIBS)
5723        {
5724            return gl::error(GL_INVALID_VALUE);
5725        }
5726
5727        gl::Context *context = gl::getNonLostContext();
5728
5729        if (context)
5730        {
5731            GLfloat vals[4] = { x, y, z, 1 };
5732            context->setVertexAttribf(index, vals);
5733        }
5734    }
5735    catch (...)
5736    {
5737        return gl::error(GL_OUT_OF_MEMORY);
5738    }
5739}
5740
5741void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values)
5742{
5743    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5744
5745    try
5746    {
5747        if (index >= gl::MAX_VERTEX_ATTRIBS)
5748        {
5749            return gl::error(GL_INVALID_VALUE);
5750        }
5751
5752        gl::Context *context = gl::getNonLostContext();
5753
5754        if (context)
5755        {
5756            GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5757            context->setVertexAttribf(index, vals);
5758        }
5759    }
5760    catch (...)
5761    {
5762        return gl::error(GL_OUT_OF_MEMORY);
5763    }
5764}
5765
5766void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5767{
5768    EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5769
5770    try
5771    {
5772        if (index >= gl::MAX_VERTEX_ATTRIBS)
5773        {
5774            return gl::error(GL_INVALID_VALUE);
5775        }
5776
5777        gl::Context *context = gl::getNonLostContext();
5778
5779        if (context)
5780        {
5781            GLfloat vals[4] = { x, y, z, w };
5782            context->setVertexAttribf(index, vals);
5783        }
5784    }
5785    catch (...)
5786    {
5787        return gl::error(GL_OUT_OF_MEMORY);
5788    }
5789}
5790
5791void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values)
5792{
5793    EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5794
5795    try
5796    {
5797        if (index >= gl::MAX_VERTEX_ATTRIBS)
5798        {
5799            return gl::error(GL_INVALID_VALUE);
5800        }
5801
5802        gl::Context *context = gl::getNonLostContext();
5803
5804        if (context)
5805        {
5806            context->setVertexAttribf(index, values);
5807        }
5808    }
5809    catch (...)
5810    {
5811        return gl::error(GL_OUT_OF_MEMORY);
5812    }
5813}
5814
5815void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
5816{
5817    EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
5818
5819    try
5820    {
5821        if (index >= gl::MAX_VERTEX_ATTRIBS)
5822        {
5823            return gl::error(GL_INVALID_VALUE);
5824        }
5825
5826        gl::Context *context = gl::getNonLostContext();
5827
5828        if (context)
5829        {
5830            context->setVertexAttribDivisor(index, divisor);
5831        }
5832    }
5833    catch (...)
5834    {
5835        return gl::error(GL_OUT_OF_MEMORY);
5836    }
5837}
5838
5839void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5840{
5841    EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5842          "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
5843          index, size, type, normalized, stride, ptr);
5844
5845    try
5846    {
5847        if (index >= gl::MAX_VERTEX_ATTRIBS)
5848        {
5849            return gl::error(GL_INVALID_VALUE);
5850        }
5851
5852        if (size < 1 || size > 4)
5853        {
5854            return gl::error(GL_INVALID_VALUE);
5855        }
5856
5857        gl::Context *context = gl::getNonLostContext();
5858
5859        switch (type)
5860        {
5861          case GL_BYTE:
5862          case GL_UNSIGNED_BYTE:
5863          case GL_SHORT:
5864          case GL_UNSIGNED_SHORT:
5865          case GL_FIXED:
5866          case GL_FLOAT:
5867            break;
5868          case GL_HALF_FLOAT:
5869          case GL_INT:
5870          case GL_UNSIGNED_INT:
5871          case GL_INT_2_10_10_10_REV:
5872          case GL_UNSIGNED_INT_2_10_10_10_REV:
5873            if (context && context->getClientVersion() < 3)
5874            {
5875                return gl::error(GL_INVALID_ENUM);
5876            }
5877            else
5878            {
5879                break;
5880            }
5881          default:
5882            return gl::error(GL_INVALID_ENUM);
5883        }
5884
5885        if (stride < 0)
5886        {
5887            return gl::error(GL_INVALID_VALUE);
5888        }
5889
5890        if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
5891        {
5892            return gl::error(GL_INVALID_OPERATION);
5893        }
5894
5895        if (context)
5896        {
5897            // [OpenGL ES 3.0.2] Section 2.8 page 24:
5898            // An INVALID_OPERATION error is generated when a non-zero vertex array object
5899            // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
5900            // and the pointer argument is not NULL.
5901            if (context->getVertexArrayHandle() != 0 && context->getArrayBufferHandle() == 0 && ptr != NULL)
5902            {
5903                return gl::error(GL_INVALID_OPERATION);
5904            }
5905
5906            context->setVertexAttribState(index, context->getArrayBuffer(), size, type,
5907                                          normalized == GL_TRUE, false, stride, ptr);
5908        }
5909    }
5910    catch (...)
5911    {
5912        return gl::error(GL_OUT_OF_MEMORY);
5913    }
5914}
5915
5916void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
5917{
5918    EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5919
5920    try
5921    {
5922        if (width < 0 || height < 0)
5923        {
5924            return gl::error(GL_INVALID_VALUE);
5925        }
5926
5927        gl::Context *context = gl::getNonLostContext();
5928
5929        if (context)
5930        {
5931            context->setViewportParams(x, y, width, height);
5932        }
5933    }
5934    catch (...)
5935    {
5936        return gl::error(GL_OUT_OF_MEMORY);
5937    }
5938}
5939
5940// OpenGL ES 3.0 functions
5941
5942void __stdcall glReadBuffer(GLenum mode)
5943{
5944    EVENT("(GLenum mode = 0x%X)", mode);
5945
5946    try
5947    {
5948        gl::Context *context = gl::getNonLostContext();
5949
5950        if (context)
5951        {
5952            if (context->getClientVersion() < 3)
5953            {
5954                return gl::error(GL_INVALID_OPERATION);
5955            }
5956
5957            // glReadBuffer
5958            UNIMPLEMENTED();
5959        }
5960    }
5961    catch (...)
5962    {
5963        return gl::error(GL_OUT_OF_MEMORY);
5964    }
5965}
5966
5967void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
5968{
5969    EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
5970          "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
5971
5972    try
5973    {
5974        gl::Context *context = gl::getNonLostContext();
5975
5976        if (context)
5977        {
5978            if (context->getClientVersion() < 3)
5979            {
5980                return gl::error(GL_INVALID_OPERATION);
5981            }
5982
5983            // glDrawRangeElements
5984            UNIMPLEMENTED();
5985        }
5986    }
5987    catch (...)
5988    {
5989        return gl::error(GL_OUT_OF_MEMORY);
5990    }
5991}
5992
5993void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
5994{
5995    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
5996          "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
5997          "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
5998          target, level, internalformat, width, height, depth, border, format, type, pixels);
5999
6000    try
6001    {
6002        gl::Context *context = gl::getNonLostContext();
6003
6004        if (context)
6005        {
6006            if (context->getClientVersion() < 3)
6007            {
6008                return gl::error(GL_INVALID_OPERATION);
6009            }
6010
6011            // validateES3TexImageFormat sets the error code if there is an error
6012            if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
6013                                               0, 0, 0, width, height, depth, border, format, type, pixels))
6014            {
6015                return;
6016            }
6017
6018            switch(target)
6019            {
6020              case GL_TEXTURE_3D:
6021                {
6022                    gl::Texture3D *texture = context->getTexture3D();
6023                    texture->setImage(level, width, height, depth, internalformat, format, type, context->getUnpackState(), pixels);
6024                }
6025                break;
6026
6027              case GL_TEXTURE_2D_ARRAY:
6028                {
6029                    gl::Texture2DArray *texture = context->getTexture2DArray();
6030                    texture->setImage(level, width, height, depth, internalformat, format, type, context->getUnpackState(), pixels);
6031                }
6032                break;
6033
6034              default:
6035                return gl::error(GL_INVALID_ENUM);
6036            }
6037        }
6038    }
6039    catch (...)
6040    {
6041        return gl::error(GL_OUT_OF_MEMORY);
6042    }
6043}
6044
6045void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
6046{
6047    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6048          "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6049          "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
6050          target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
6051
6052    try
6053    {
6054        gl::Context *context = gl::getNonLostContext();
6055
6056        if (context)
6057        {
6058            if (context->getClientVersion() < 3)
6059            {
6060                return gl::error(GL_INVALID_OPERATION);
6061            }
6062
6063            // validateES3TexImageFormat sets the error code if there is an error
6064            if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
6065                                               xoffset, yoffset, zoffset, width, height, depth, 0,
6066                                               format, type, pixels))
6067            {
6068                return;
6069            }
6070
6071            // Zero sized uploads are valid but no-ops
6072            if (width == 0 || height == 0 || depth == 0)
6073            {
6074                return;
6075            }
6076
6077            switch(target)
6078            {
6079              case GL_TEXTURE_3D:
6080                {
6081                    gl::Texture3D *texture = context->getTexture3D();
6082                    texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackState(), pixels);
6083                }
6084                break;
6085
6086              case GL_TEXTURE_2D_ARRAY:
6087                {
6088                    gl::Texture2DArray *texture = context->getTexture2DArray();
6089                    texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackState(), pixels);
6090                }
6091                break;
6092
6093              default:
6094                return gl::error(GL_INVALID_ENUM);
6095            }
6096        }
6097    }
6098    catch (...)
6099    {
6100        return gl::error(GL_OUT_OF_MEMORY);
6101    }
6102}
6103
6104void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6105{
6106    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6107          "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6108          target, level, xoffset, yoffset, zoffset, x, y, width, height);
6109
6110    try
6111    {
6112        gl::Context *context = gl::getNonLostContext();
6113
6114        if (context)
6115        {
6116            if (context->getClientVersion() < 3)
6117            {
6118                return gl::error(GL_INVALID_OPERATION);
6119            }
6120
6121            if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset,
6122                                                   x, y, width, height, 0))
6123            {
6124                return;
6125            }
6126
6127            gl::Framebuffer *framebuffer = context->getReadFramebuffer();
6128            gl::Texture *texture = NULL;
6129            switch (target)
6130            {
6131              case GL_TEXTURE_3D:
6132                texture = context->getTexture3D();
6133                break;
6134
6135              case GL_TEXTURE_2D_ARRAY:
6136                texture = context->getTexture2DArray();
6137                break;
6138
6139              default:
6140                return gl::error(GL_INVALID_ENUM);
6141            }
6142
6143            texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6144        }
6145    }
6146    catch (...)
6147    {
6148        return gl::error(GL_OUT_OF_MEMORY);
6149    }
6150}
6151
6152void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
6153{
6154    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6155          "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
6156          "const GLvoid* data = 0x%0.8p)",
6157          target, level, internalformat, width, height, depth, border, imageSize, data);
6158
6159    try
6160    {
6161        gl::Context *context = gl::getNonLostContext();
6162
6163        if (context)
6164        {
6165            if (context->getClientVersion() < 3)
6166            {
6167                return gl::error(GL_INVALID_OPERATION);
6168            }
6169
6170            if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height))
6171            {
6172                return gl::error(GL_INVALID_VALUE);
6173            }
6174
6175            // validateES3TexImageFormat sets the error code if there is an error
6176            if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
6177                                               0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data))
6178            {
6179                return;
6180            }
6181
6182            switch(target)
6183            {
6184              case GL_TEXTURE_3D:
6185                {
6186                    gl::Texture3D *texture = context->getTexture3D();
6187                    texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6188                }
6189                break;
6190
6191              case GL_TEXTURE_2D_ARRAY:
6192                {
6193                    gl::Texture2DArray *texture = context->getTexture2DArray();
6194                    texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6195                }
6196                break;
6197
6198              default:
6199                return gl::error(GL_INVALID_ENUM);
6200            }
6201        }
6202    }
6203    catch (...)
6204    {
6205        return gl::error(GL_OUT_OF_MEMORY);
6206    }
6207}
6208
6209void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
6210{
6211    EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6212        "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6213        "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
6214        target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6215
6216    try
6217    {
6218        gl::Context *context = gl::getNonLostContext();
6219
6220        if (context)
6221        {
6222            if (context->getClientVersion() < 3)
6223            {
6224                return gl::error(GL_INVALID_OPERATION);
6225            }
6226
6227            if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, context->getClientVersion(), width, height))
6228            {
6229                return gl::error(GL_INVALID_VALUE);
6230            }
6231
6232            if (!data)
6233            {
6234                return gl::error(GL_INVALID_VALUE);
6235            }
6236
6237            // validateES3TexImageFormat sets the error code if there is an error
6238            if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
6239                                               0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data))
6240            {
6241                return;
6242            }
6243
6244            // Zero sized uploads are valid but no-ops
6245            if (width == 0 || height == 0)
6246            {
6247                return;
6248            }
6249
6250            switch(target)
6251            {
6252              case GL_TEXTURE_3D:
6253                {
6254                    gl::Texture3D *texture = context->getTexture3D();
6255                    texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
6256                                                format, imageSize, data);
6257                }
6258                break;
6259
6260              case GL_TEXTURE_2D_ARRAY:
6261                {
6262                    gl::Texture2DArray *texture = context->getTexture2DArray();
6263                    texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
6264                                                format, imageSize, data);
6265                }
6266                break;
6267
6268            default:
6269                return gl::error(GL_INVALID_ENUM);
6270            }
6271        }
6272    }
6273    catch (...)
6274    {
6275        return gl::error(GL_OUT_OF_MEMORY);
6276    }
6277}
6278
6279void __stdcall glGenQueries(GLsizei n, GLuint* ids)
6280{
6281    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
6282
6283    try
6284    {
6285        gl::Context *context = gl::getNonLostContext();
6286
6287        if (context)
6288        {
6289            if (context->getClientVersion() < 3)
6290            {
6291                return gl::error(GL_INVALID_OPERATION);
6292            }
6293
6294            if (n < 0)
6295            {
6296                return gl::error(GL_INVALID_VALUE);
6297            }
6298
6299            for (GLsizei i = 0; i < n; i++)
6300            {
6301                ids[i] = context->createQuery();
6302            }
6303        }
6304    }
6305    catch (...)
6306    {
6307        return gl::error(GL_OUT_OF_MEMORY);
6308    }
6309}
6310
6311void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids)
6312{
6313    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
6314
6315    try
6316    {
6317        gl::Context *context = gl::getNonLostContext();
6318
6319        if (context)
6320        {
6321            if (context->getClientVersion() < 3)
6322            {
6323                return gl::error(GL_INVALID_OPERATION);
6324            }
6325
6326            if (n < 0)
6327            {
6328                return gl::error(GL_INVALID_VALUE);
6329            }
6330
6331            for (GLsizei i = 0; i < n; i++)
6332            {
6333                context->deleteQuery(ids[i]);
6334            }
6335        }
6336    }
6337    catch (...)
6338    {
6339        return gl::error(GL_OUT_OF_MEMORY);
6340    }
6341}
6342
6343GLboolean __stdcall glIsQuery(GLuint id)
6344{
6345    EVENT("(GLuint id = %u)", id);
6346
6347    try
6348    {
6349        gl::Context *context = gl::getNonLostContext();
6350
6351        if (context)
6352        {
6353            if (context->getClientVersion() < 3)
6354            {
6355                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
6356            }
6357
6358            return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
6359        }
6360    }
6361    catch (...)
6362    {
6363        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
6364    }
6365
6366    return GL_FALSE;
6367}
6368
6369void __stdcall glBeginQuery(GLenum target, GLuint id)
6370{
6371    EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
6372
6373    try
6374    {
6375        gl::Context *context = gl::getNonLostContext();
6376
6377        if (context)
6378        {
6379            if (context->getClientVersion() < 3)
6380            {
6381                return gl::error(GL_INVALID_OPERATION);
6382            }
6383
6384            if (!ValidateBeginQuery(context, target, id))
6385            {
6386                return;
6387            }
6388            context->beginQuery(target, id);
6389        }
6390    }
6391    catch (...)
6392    {
6393        return gl::error(GL_OUT_OF_MEMORY);
6394    }
6395}
6396
6397void __stdcall glEndQuery(GLenum target)
6398{
6399    EVENT("(GLenum target = 0x%X)", target);
6400
6401    try
6402    {
6403        gl::Context *context = gl::getNonLostContext();
6404
6405        if (context)
6406        {
6407            if (context->getClientVersion() < 3)
6408            {
6409                return gl::error(GL_INVALID_OPERATION);
6410            }
6411
6412            if (!ValidateEndQuery(context, target))
6413            {
6414                return;
6415            }
6416
6417            context->endQuery(target);
6418        }
6419    }
6420    catch (...)
6421    {
6422        return gl::error(GL_OUT_OF_MEMORY);
6423    }
6424}
6425
6426void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params)
6427{
6428    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
6429
6430    try
6431    {
6432        gl::Context *context = gl::getNonLostContext();
6433
6434        if (context)
6435        {
6436            if (context->getClientVersion() < 3)
6437            {
6438                return gl::error(GL_INVALID_OPERATION);
6439            }
6440
6441            if (!ValidQueryType(context, target))
6442            {
6443                return gl::error(GL_INVALID_ENUM);
6444            }
6445
6446            switch (pname)
6447            {
6448              case GL_CURRENT_QUERY:
6449                params[0] = static_cast<GLint>(context->getActiveQueryId(target));
6450                break;
6451
6452              default:
6453                return gl::error(GL_INVALID_ENUM);
6454            }
6455        }
6456    }
6457    catch (...)
6458    {
6459        return gl::error(GL_OUT_OF_MEMORY);
6460    }
6461}
6462
6463void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
6464{
6465    EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
6466
6467    try
6468    {
6469        gl::Context *context = gl::getNonLostContext();
6470
6471        if (context)
6472        {
6473            if (context->getClientVersion() < 3)
6474            {
6475                return gl::error(GL_INVALID_OPERATION);
6476            }
6477
6478            gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
6479
6480            if (!queryObject)
6481            {
6482                return gl::error(GL_INVALID_OPERATION);
6483            }
6484
6485            if (context->getActiveQueryId(queryObject->getType()) == id)
6486            {
6487                return gl::error(GL_INVALID_OPERATION);
6488            }
6489
6490            switch(pname)
6491            {
6492              case GL_QUERY_RESULT:
6493                params[0] = queryObject->getResult();
6494                break;
6495              case GL_QUERY_RESULT_AVAILABLE:
6496                params[0] = queryObject->isResultAvailable();
6497                break;
6498              default:
6499                return gl::error(GL_INVALID_ENUM);
6500            }
6501        }
6502    }
6503    catch (...)
6504    {
6505        return gl::error(GL_OUT_OF_MEMORY);
6506    }
6507}
6508
6509GLboolean __stdcall glUnmapBuffer(GLenum target)
6510{
6511    EVENT("(GLenum target = 0x%X)", target);
6512
6513    try
6514    {
6515        gl::Context *context = gl::getNonLostContext();
6516
6517        if (context)
6518        {
6519            if (context->getClientVersion() < 3)
6520            {
6521                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
6522            }
6523
6524            return glUnmapBufferOES(target);
6525        }
6526    }
6527    catch (...)
6528    {
6529        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
6530    }
6531
6532    return GL_FALSE;
6533}
6534
6535void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
6536{
6537    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
6538
6539    try
6540    {
6541        gl::Context *context = gl::getNonLostContext();
6542
6543        if (context)
6544        {
6545            if (context->getClientVersion() < 3)
6546            {
6547                return gl::error(GL_INVALID_OPERATION);
6548            }
6549
6550            glGetBufferPointervOES(target, pname, params);
6551        }
6552    }
6553    catch (...)
6554    {
6555        return gl::error(GL_OUT_OF_MEMORY);
6556    }
6557}
6558
6559void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs)
6560{
6561    try
6562    {
6563        gl::Context *context = gl::getNonLostContext();
6564
6565        if (context)
6566        {
6567            if (context->getClientVersion() < 3)
6568            {
6569                return gl::error(GL_INVALID_OPERATION);
6570            }
6571
6572            glDrawBuffersEXT(n, bufs);
6573        }
6574    }
6575    catch (...)
6576    {
6577        return gl::error(GL_OUT_OF_MEMORY);
6578    }
6579}
6580
6581void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6582{
6583    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6584          location, count, transpose, value);
6585
6586    try
6587    {
6588        gl::Context *context = gl::getNonLostContext();
6589
6590        if (context)
6591        {
6592            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
6593            {
6594                return;
6595            }
6596
6597            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6598            programBinary->setUniformMatrix2x3fv(location, count, transpose, value);
6599        }
6600    }
6601    catch (...)
6602    {
6603        return gl::error(GL_OUT_OF_MEMORY);
6604    }
6605}
6606
6607void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6608{
6609    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6610          location, count, transpose, value);
6611
6612    try
6613    {
6614        gl::Context *context = gl::getNonLostContext();
6615
6616        if (context)
6617        {
6618            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
6619            {
6620                return;
6621            }
6622
6623            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6624            programBinary->setUniformMatrix3x2fv(location, count, transpose, value);
6625        }
6626    }
6627    catch (...)
6628    {
6629        return gl::error(GL_OUT_OF_MEMORY);
6630    }
6631}
6632
6633void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6634{
6635    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6636          location, count, transpose, value);
6637
6638    try
6639    {
6640        gl::Context *context = gl::getNonLostContext();
6641
6642        if (context)
6643        {
6644            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
6645            {
6646                return;
6647            }
6648
6649            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6650            programBinary->setUniformMatrix2x4fv(location, count, transpose, value);
6651        }
6652    }
6653    catch (...)
6654    {
6655        return gl::error(GL_OUT_OF_MEMORY);
6656    }
6657}
6658
6659void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6660{
6661    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6662          location, count, transpose, value);
6663
6664    try
6665    {
6666        gl::Context *context = gl::getNonLostContext();
6667
6668        if (context)
6669        {
6670            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
6671            {
6672                return;
6673            }
6674
6675            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6676            programBinary->setUniformMatrix4x2fv(location, count, transpose, value);
6677        }
6678    }
6679    catch (...)
6680    {
6681        return gl::error(GL_OUT_OF_MEMORY);
6682    }
6683}
6684
6685void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6686{
6687    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6688          location, count, transpose, value);
6689
6690    try
6691    {
6692        gl::Context *context = gl::getNonLostContext();
6693
6694        if (context)
6695        {
6696            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
6697            {
6698                return;
6699            }
6700
6701            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6702            programBinary->setUniformMatrix3x4fv(location, count, transpose, value);
6703        }
6704    }
6705    catch (...)
6706    {
6707        return gl::error(GL_OUT_OF_MEMORY);
6708    }
6709}
6710
6711void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
6712{
6713    EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
6714          location, count, transpose, value);
6715
6716    try
6717    {
6718        gl::Context *context = gl::getNonLostContext();
6719
6720        if (context)
6721        {
6722            if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
6723            {
6724                return;
6725            }
6726
6727            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
6728            programBinary->setUniformMatrix4x3fv(location, count, transpose, value);
6729        }
6730    }
6731    catch (...)
6732    {
6733        return gl::error(GL_OUT_OF_MEMORY);
6734    }
6735}
6736
6737void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6738{
6739    EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
6740          "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6741          srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6742
6743    try
6744    {
6745        gl::Context *context = gl::getNonLostContext();
6746        if (context)
6747        {
6748            if (context->getClientVersion() < 3)
6749            {
6750                return gl::error(GL_INVALID_OPERATION);
6751            }
6752
6753            if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
6754                                                   dstX0, dstY0, dstX1, dstY1, mask, filter,
6755                                                   false))
6756            {
6757                return;
6758            }
6759
6760            context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
6761                                     mask, filter);
6762        }
6763    }
6764    catch (...)
6765    {
6766        return gl::error(GL_OUT_OF_MEMORY);
6767    }
6768}
6769
6770void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
6771{
6772    EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
6773        target, samples, internalformat, width, height);
6774
6775    try
6776    {
6777        gl::Context *context = gl::getNonLostContext();
6778
6779        if (context)
6780        {
6781            if (context->getClientVersion() < 3)
6782            {
6783                return gl::error(GL_INVALID_OPERATION);
6784            }
6785
6786            if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
6787                                                       width, height, false))
6788            {
6789                return;
6790            }
6791
6792            context->setRenderbufferStorage(width, height, internalformat, samples);
6793        }
6794    }
6795    catch (...)
6796    {
6797        return gl::error(GL_OUT_OF_MEMORY);
6798    }
6799}
6800
6801void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
6802{
6803    EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
6804        target, attachment, texture, level, layer);
6805
6806    try
6807    {
6808        gl::Context *context = gl::getNonLostContext();
6809
6810        if (context)
6811        {
6812            if (context->getClientVersion() < 3)
6813            {
6814                return gl::error(GL_INVALID_OPERATION);
6815            }
6816
6817            if (!ValidateES3FramebufferTextureParameters(context, target, attachment, GL_NONE, texture, level, layer, true))
6818            {
6819                return;
6820            }
6821
6822            gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
6823            ASSERT(framebuffer);
6824
6825            gl::Texture *textureObject = context->getTexture(texture);
6826            GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE;
6827
6828            if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
6829            {
6830                const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
6831                framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer);
6832            }
6833            else
6834            {
6835                switch (attachment)
6836                {
6837                case GL_DEPTH_ATTACHMENT:         framebuffer->setDepthbuffer(textarget, texture, level, layer);        break;
6838                case GL_STENCIL_ATTACHMENT:       framebuffer->setStencilbuffer(textarget, texture, level, layer);      break;
6839                case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break;
6840                }
6841            }
6842        }
6843    }
6844    catch (...)
6845    {
6846        return gl::error(GL_OUT_OF_MEMORY);
6847    }
6848}
6849
6850GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
6851{
6852    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
6853          target, offset, length, access);
6854
6855    try
6856    {
6857        gl::Context *context = gl::getNonLostContext();
6858
6859        if (context)
6860        {
6861            if (context->getClientVersion() < 3)
6862            {
6863                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
6864            }
6865
6866            return glMapBufferRangeEXT(target, offset, length, access);
6867        }
6868    }
6869    catch (...)
6870    {
6871        return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast<GLvoid*>(NULL));
6872    }
6873
6874    return NULL;
6875}
6876
6877void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
6878{
6879    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
6880
6881    try
6882    {
6883        gl::Context *context = gl::getNonLostContext();
6884
6885        if (context)
6886        {
6887            if (context->getClientVersion() < 3)
6888            {
6889                return gl::error(GL_INVALID_OPERATION);
6890            }
6891
6892            glFlushMappedBufferRangeEXT(target, offset, length);
6893        }
6894    }
6895    catch (...)
6896    {
6897        return gl::error(GL_OUT_OF_MEMORY);
6898    }
6899}
6900
6901void __stdcall glBindVertexArray(GLuint array)
6902{
6903    EVENT("(GLuint array = %u)", array);
6904
6905    try
6906    {
6907        gl::Context *context = gl::getNonLostContext();
6908
6909        if (context)
6910        {
6911            if (context->getClientVersion() < 3)
6912            {
6913                return gl::error(GL_INVALID_OPERATION);
6914            }
6915
6916            gl::VertexArray *vao = context->getVertexArray(array);
6917
6918            if (!vao)
6919            {
6920                // The default VAO should always exist
6921                ASSERT(array != 0);
6922                return gl::error(GL_INVALID_OPERATION);
6923            }
6924
6925            context->bindVertexArray(array);
6926        }
6927    }
6928    catch (...)
6929    {
6930        return gl::error(GL_OUT_OF_MEMORY);
6931    }
6932}
6933
6934void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
6935{
6936    EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
6937
6938    try
6939    {
6940        gl::Context *context = gl::getNonLostContext();
6941
6942        if (context)
6943        {
6944            if (context->getClientVersion() < 3)
6945            {
6946                return gl::error(GL_INVALID_OPERATION);
6947            }
6948
6949            if (n < 0)
6950            {
6951                return gl::error(GL_INVALID_VALUE);
6952            }
6953
6954            for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
6955            {
6956                if (arrays[arrayIndex] != 0)
6957                {
6958                    context->deleteVertexArray(arrays[arrayIndex]);
6959                }
6960            }
6961        }
6962    }
6963    catch (...)
6964    {
6965        return gl::error(GL_OUT_OF_MEMORY);
6966    }
6967}
6968
6969void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays)
6970{
6971    EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
6972
6973    try
6974    {
6975        gl::Context *context = gl::getNonLostContext();
6976
6977        if (context)
6978        {
6979            if (context->getClientVersion() < 3)
6980            {
6981                return gl::error(GL_INVALID_OPERATION);
6982            }
6983
6984            if (n < 0)
6985            {
6986                return gl::error(GL_INVALID_VALUE);
6987            }
6988
6989            for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
6990            {
6991                arrays[arrayIndex] = context->createVertexArray();
6992            }
6993        }
6994    }
6995    catch (...)
6996    {
6997        return gl::error(GL_OUT_OF_MEMORY);
6998    }
6999}
7000
7001GLboolean __stdcall glIsVertexArray(GLuint array)
7002{
7003    EVENT("(GLuint array = %u)", array);
7004
7005    try
7006    {
7007        gl::Context *context = gl::getNonLostContext();
7008
7009        if (context)
7010        {
7011            if (context->getClientVersion() < 3)
7012            {
7013                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
7014            }
7015
7016            if (array == 0)
7017            {
7018                return GL_FALSE;
7019            }
7020
7021            gl::VertexArray *vao = context->getVertexArray(array);
7022
7023            return (vao != NULL ? GL_TRUE : GL_FALSE);
7024        }
7025    }
7026    catch (...)
7027    {
7028        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
7029    }
7030
7031    return GL_FALSE;
7032}
7033
7034void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
7035{
7036    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
7037          target, index, data);
7038
7039    try
7040    {
7041        gl::Context *context = gl::getNonLostContext();
7042
7043        if (context)
7044        {
7045            if (context->getClientVersion() < 3)
7046            {
7047                return gl::error(GL_INVALID_OPERATION);
7048            }
7049
7050            switch (target)
7051            {
7052              case GL_TRANSFORM_FEEDBACK_BUFFER_START:
7053              case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
7054              case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
7055                if (index >= context->getMaxTransformFeedbackBufferBindings())
7056                    return gl::error(GL_INVALID_VALUE);
7057                break;
7058              case GL_UNIFORM_BUFFER_START:
7059              case GL_UNIFORM_BUFFER_SIZE:
7060              case GL_UNIFORM_BUFFER_BINDING:
7061                if (index >= context->getMaximumCombinedUniformBufferBindings())
7062                    return gl::error(GL_INVALID_VALUE);
7063                break;
7064              default:
7065                return gl::error(GL_INVALID_ENUM);
7066            }
7067
7068            if (!(context->getIndexedIntegerv(target, index, data)))
7069            {
7070                GLenum nativeType;
7071                unsigned int numParams = 0;
7072                if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
7073                    return gl::error(GL_INVALID_ENUM);
7074
7075                if (numParams == 0)
7076                    return; // it is known that pname is valid, but there are no parameters to return
7077
7078                if (nativeType == GL_INT_64_ANGLEX)
7079                {
7080                    GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
7081                    GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
7082                    GLint64 *int64Params = new GLint64[numParams];
7083
7084                    context->getIndexedInteger64v(target, index, int64Params);
7085
7086                    for (unsigned int i = 0; i < numParams; ++i)
7087                    {
7088                        GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
7089                        data[i] = static_cast<GLint>(clampedValue);
7090                    }
7091
7092                    delete [] int64Params;
7093                }
7094                else
7095                {
7096                    UNREACHABLE();
7097                }
7098            }
7099        }
7100    }
7101    catch (...)
7102    {
7103        return gl::error(GL_OUT_OF_MEMORY);
7104    }
7105}
7106
7107void __stdcall glBeginTransformFeedback(GLenum primitiveMode)
7108{
7109    EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
7110
7111    try
7112    {
7113        gl::Context *context = gl::getNonLostContext();
7114
7115        if (context)
7116        {
7117            if (context->getClientVersion() < 3)
7118            {
7119                return gl::error(GL_INVALID_OPERATION);
7120            }
7121
7122            switch (primitiveMode)
7123            {
7124              case GL_TRIANGLES:
7125              case GL_LINES:
7126              case GL_POINTS:
7127                break;
7128              default:
7129                return gl::error(GL_INVALID_ENUM);
7130            }
7131
7132            gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback();
7133            ASSERT(transformFeedback != NULL);
7134
7135            if (transformFeedback->isStarted())
7136            {
7137                return gl::error(GL_INVALID_OPERATION);
7138            }
7139
7140            if (transformFeedback->isPaused())
7141            {
7142                transformFeedback->resume();
7143            }
7144            else
7145            {
7146                transformFeedback->start(primitiveMode);
7147            }
7148        }
7149    }
7150    catch (...)
7151    {
7152        return gl::error(GL_OUT_OF_MEMORY);
7153    }
7154}
7155
7156void __stdcall glEndTransformFeedback(void)
7157{
7158    EVENT("(void)");
7159
7160    try
7161    {
7162        gl::Context *context = gl::getNonLostContext();
7163
7164        if (context)
7165        {
7166            if (context->getClientVersion() < 3)
7167            {
7168                return gl::error(GL_INVALID_OPERATION);
7169            }
7170
7171            gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback();
7172            ASSERT(transformFeedback != NULL);
7173
7174            if (!transformFeedback->isStarted())
7175            {
7176                return gl::error(GL_INVALID_OPERATION);
7177            }
7178
7179            transformFeedback->stop();
7180        }
7181    }
7182    catch (...)
7183    {
7184        return gl::error(GL_OUT_OF_MEMORY);
7185    }
7186}
7187
7188void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
7189{
7190    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
7191          target, index, buffer, offset, size);
7192
7193    try
7194    {
7195        gl::Context *context = gl::getNonLostContext();
7196
7197        if (context)
7198        {
7199            if (context->getClientVersion() < 3)
7200            {
7201                return gl::error(GL_INVALID_OPERATION);
7202            }
7203
7204            switch (target)
7205            {
7206              case GL_TRANSFORM_FEEDBACK_BUFFER:
7207                if (index >= context->getMaxTransformFeedbackBufferBindings())
7208                {
7209                    return gl::error(GL_INVALID_VALUE);
7210                }
7211                break;
7212
7213              case GL_UNIFORM_BUFFER:
7214                if (index >= context->getMaximumCombinedUniformBufferBindings())
7215                {
7216                    return gl::error(GL_INVALID_VALUE);
7217                }
7218                break;
7219
7220              default:
7221                return gl::error(GL_INVALID_ENUM);
7222            }
7223
7224            if (buffer != 0 && size <= 0)
7225            {
7226                return gl::error(GL_INVALID_VALUE);
7227            }
7228
7229            switch (target)
7230            {
7231              case GL_TRANSFORM_FEEDBACK_BUFFER:
7232
7233                // size and offset must be a multiple of 4
7234                if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
7235                {
7236                    return gl::error(GL_INVALID_VALUE);
7237                }
7238
7239                context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
7240                context->bindGenericTransformFeedbackBuffer(buffer);
7241                break;
7242
7243              case GL_UNIFORM_BUFFER:
7244
7245                // it is an error to bind an offset not a multiple of the alignment
7246                if (buffer != 0 && (offset % context->getUniformBufferOffsetAlignment()) != 0)
7247                {
7248                    return gl::error(GL_INVALID_VALUE);
7249                }
7250
7251                context->bindIndexedUniformBuffer(buffer, index, offset, size);
7252                context->bindGenericUniformBuffer(buffer);
7253                break;
7254
7255              default:
7256                UNREACHABLE();
7257            }
7258        }
7259    }
7260    catch (...)
7261    {
7262        return gl::error(GL_OUT_OF_MEMORY);
7263    }
7264}
7265
7266void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
7267{
7268    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
7269          target, index, buffer);
7270
7271    try
7272    {
7273        gl::Context *context = gl::getNonLostContext();
7274
7275        if (context)
7276        {
7277            if (context->getClientVersion() < 3)
7278            {
7279                return gl::error(GL_INVALID_OPERATION);
7280            }
7281
7282            switch (target)
7283            {
7284              case GL_TRANSFORM_FEEDBACK_BUFFER:
7285                if (index >= context->getMaxTransformFeedbackBufferBindings())
7286                {
7287                    return gl::error(GL_INVALID_VALUE);
7288                }
7289                break;
7290
7291              case GL_UNIFORM_BUFFER:
7292                if (index >= context->getMaximumCombinedUniformBufferBindings())
7293                {
7294                    return gl::error(GL_INVALID_VALUE);
7295                }
7296                break;
7297
7298              default:
7299                return gl::error(GL_INVALID_ENUM);
7300            }
7301
7302            switch (target)
7303            {
7304              case GL_TRANSFORM_FEEDBACK_BUFFER:
7305                context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
7306                context->bindGenericTransformFeedbackBuffer(buffer);
7307                break;
7308
7309              case GL_UNIFORM_BUFFER:
7310                context->bindIndexedUniformBuffer(buffer, index, 0, 0);
7311                context->bindGenericUniformBuffer(buffer);
7312                break;
7313
7314              default:
7315                UNREACHABLE();
7316            }
7317        }
7318    }
7319    catch (...)
7320    {
7321        return gl::error(GL_OUT_OF_MEMORY);
7322    }
7323}
7324
7325void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
7326{
7327    EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
7328          program, count, varyings, bufferMode);
7329
7330    try
7331    {
7332        gl::Context *context = gl::getNonLostContext();
7333
7334        if (context)
7335        {
7336            if (context->getClientVersion() < 3)
7337            {
7338                return gl::error(GL_INVALID_OPERATION);
7339            }
7340
7341            if (count < 0)
7342            {
7343                return gl::error(GL_INVALID_VALUE);
7344            }
7345
7346            switch (bufferMode)
7347            {
7348              case GL_INTERLEAVED_ATTRIBS:
7349                break;
7350              case GL_SEPARATE_ATTRIBS:
7351                if (static_cast<GLuint>(count) > context->getMaxTransformFeedbackBufferBindings())
7352                {
7353                    return gl::error(GL_INVALID_VALUE);
7354                }
7355                break;
7356              default:
7357                return gl::error(GL_INVALID_ENUM);
7358            }
7359
7360            if (!gl::ValidProgram(context, program))
7361            {
7362                return;
7363            }
7364
7365            gl::Program *programObject = context->getProgram(program);
7366            ASSERT(programObject);
7367
7368            programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
7369        }
7370    }
7371    catch (...)
7372    {
7373        return gl::error(GL_OUT_OF_MEMORY);
7374    }
7375}
7376
7377void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
7378{
7379    EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
7380          "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
7381          program, index, bufSize, length, size, type, name);
7382
7383    try
7384    {
7385        gl::Context *context = gl::getNonLostContext();
7386
7387        if (context)
7388        {
7389            if (context->getClientVersion() < 3)
7390            {
7391                return gl::error(GL_INVALID_OPERATION);
7392            }
7393
7394            if (bufSize < 0)
7395            {
7396                return gl::error(GL_INVALID_VALUE);
7397            }
7398
7399            if (!gl::ValidProgram(context, program))
7400            {
7401                return;
7402            }
7403
7404            gl::Program *programObject = context->getProgram(program);
7405            ASSERT(programObject);
7406
7407            if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
7408            {
7409                return gl::error(GL_INVALID_VALUE);
7410            }
7411
7412            programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
7413        }
7414    }
7415    catch (...)
7416    {
7417        return gl::error(GL_OUT_OF_MEMORY);
7418    }
7419}
7420
7421void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
7422{
7423    EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
7424          index, size, type, stride, pointer);
7425
7426    try
7427    {
7428        gl::Context *context = gl::getNonLostContext();
7429
7430        if (context)
7431        {
7432            if (context->getClientVersion() < 3)
7433            {
7434                return gl::error(GL_INVALID_OPERATION);
7435            }
7436        }
7437
7438        if (index >= gl::MAX_VERTEX_ATTRIBS)
7439        {
7440            return gl::error(GL_INVALID_VALUE);
7441        }
7442
7443        if (size < 1 || size > 4)
7444        {
7445            return gl::error(GL_INVALID_VALUE);
7446        }
7447
7448        switch (type)
7449        {
7450          case GL_BYTE:
7451          case GL_UNSIGNED_BYTE:
7452          case GL_SHORT:
7453          case GL_UNSIGNED_SHORT:
7454          case GL_INT:
7455          case GL_UNSIGNED_INT:
7456          case GL_INT_2_10_10_10_REV:
7457          case GL_UNSIGNED_INT_2_10_10_10_REV:
7458            break;
7459          default:
7460            return gl::error(GL_INVALID_ENUM);
7461        }
7462
7463        if (stride < 0)
7464        {
7465            return gl::error(GL_INVALID_VALUE);
7466        }
7467
7468        if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
7469        {
7470            return gl::error(GL_INVALID_OPERATION);
7471        }
7472
7473        if (context)
7474        {
7475            // [OpenGL ES 3.0.2] Section 2.8 page 24:
7476            // An INVALID_OPERATION error is generated when a non-zero vertex array object
7477            // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
7478            // and the pointer argument is not NULL.
7479            if (context->getVertexArrayHandle() != 0 && context->getArrayBufferHandle() == 0 && pointer != NULL)
7480            {
7481                return gl::error(GL_INVALID_OPERATION);
7482            }
7483
7484            context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, true,
7485                                          stride, pointer);
7486        }
7487    }
7488    catch (...)
7489    {
7490        return gl::error(GL_OUT_OF_MEMORY);
7491    }
7492}
7493
7494void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
7495{
7496    EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
7497          index, pname, params);
7498
7499    try
7500    {
7501        gl::Context *context = gl::getNonLostContext();
7502
7503        if (context)
7504        {
7505            if (context->getClientVersion() < 3)
7506            {
7507                return gl::error(GL_INVALID_OPERATION);
7508            }
7509
7510            if (index >= gl::MAX_VERTEX_ATTRIBS)
7511            {
7512                return gl::error(GL_INVALID_VALUE);
7513            }
7514
7515            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
7516
7517            if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion()))
7518            {
7519                return;
7520            }
7521
7522            if (pname == GL_CURRENT_VERTEX_ATTRIB)
7523            {
7524                const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
7525                for (int i = 0; i < 4; ++i)
7526                {
7527                    params[i] = currentValueData.IntValues[i];
7528                }
7529            }
7530            else
7531            {
7532                *params = attribState.querySingleParameter<GLint>(pname);
7533            }
7534        }
7535    }
7536    catch (...)
7537    {
7538        return gl::error(GL_OUT_OF_MEMORY);
7539    }
7540}
7541
7542void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
7543{
7544    EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
7545          index, pname, params);
7546
7547    try
7548    {
7549        gl::Context *context = gl::getNonLostContext();
7550
7551        if (context)
7552        {
7553            if (context->getClientVersion() < 3)
7554            {
7555                return gl::error(GL_INVALID_OPERATION);
7556            }
7557
7558            if (index >= gl::MAX_VERTEX_ATTRIBS)
7559            {
7560                return gl::error(GL_INVALID_VALUE);
7561            }
7562
7563            const gl::VertexAttribute &attribState = context->getVertexAttribState(index);
7564
7565            if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion()))
7566            {
7567                return;
7568            }
7569
7570            if (pname == GL_CURRENT_VERTEX_ATTRIB)
7571            {
7572                const gl::VertexAttribCurrentValueData &currentValueData = context->getVertexAttribCurrentValue(index);
7573                for (int i = 0; i < 4; ++i)
7574                {
7575                    params[i] = currentValueData.UnsignedIntValues[i];
7576                }
7577            }
7578            else
7579            {
7580                *params = attribState.querySingleParameter<GLuint>(pname);
7581            }
7582        }
7583    }
7584    catch (...)
7585    {
7586        return gl::error(GL_OUT_OF_MEMORY);
7587    }
7588}
7589
7590void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
7591{
7592    EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
7593          index, x, y, z, w);
7594
7595    try
7596    {
7597        gl::Context *context = gl::getNonLostContext();
7598
7599        if (context)
7600        {
7601            if (context->getClientVersion() < 3)
7602            {
7603                return gl::error(GL_INVALID_OPERATION);
7604            }
7605
7606            if (index >= gl::MAX_VERTEX_ATTRIBS)
7607            {
7608                return gl::error(GL_INVALID_VALUE);
7609            }
7610
7611            GLint vals[4] = { x, y, z, w };
7612            context->setVertexAttribi(index, vals);
7613        }
7614    }
7615    catch (...)
7616    {
7617        return gl::error(GL_OUT_OF_MEMORY);
7618    }
7619}
7620
7621void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
7622{
7623    EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
7624          index, x, y, z, w);
7625
7626    try
7627    {
7628        gl::Context *context = gl::getNonLostContext();
7629
7630        if (context)
7631        {
7632            if (context->getClientVersion() < 3)
7633            {
7634                return gl::error(GL_INVALID_OPERATION);
7635            }
7636
7637            if (index >= gl::MAX_VERTEX_ATTRIBS)
7638            {
7639                return gl::error(GL_INVALID_VALUE);
7640            }
7641
7642            GLuint vals[4] = { x, y, z, w };
7643            context->setVertexAttribu(index, vals);
7644        }
7645    }
7646    catch (...)
7647    {
7648        return gl::error(GL_OUT_OF_MEMORY);
7649    }
7650}
7651
7652void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v)
7653{
7654    EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
7655
7656    try
7657    {
7658        gl::Context *context = gl::getNonLostContext();
7659
7660        if (context)
7661        {
7662            if (context->getClientVersion() < 3)
7663            {
7664                return gl::error(GL_INVALID_OPERATION);
7665            }
7666
7667            if (index >= gl::MAX_VERTEX_ATTRIBS)
7668            {
7669                return gl::error(GL_INVALID_VALUE);
7670            }
7671
7672            context->setVertexAttribi(index, v);
7673        }
7674    }
7675    catch (...)
7676    {
7677        return gl::error(GL_OUT_OF_MEMORY);
7678    }
7679}
7680
7681void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v)
7682{
7683    EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
7684
7685    try
7686    {
7687        gl::Context *context = gl::getNonLostContext();
7688
7689        if (context)
7690        {
7691            if (context->getClientVersion() < 3)
7692            {
7693                return gl::error(GL_INVALID_OPERATION);
7694            }
7695
7696            if (index >= gl::MAX_VERTEX_ATTRIBS)
7697            {
7698                return gl::error(GL_INVALID_VALUE);
7699            }
7700
7701            context->setVertexAttribu(index, v);
7702        }
7703    }
7704    catch (...)
7705    {
7706        return gl::error(GL_OUT_OF_MEMORY);
7707    }
7708}
7709
7710void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params)
7711{
7712    EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
7713          program, location, params);
7714
7715    try
7716    {
7717        gl::Context *context = gl::getNonLostContext();
7718
7719        if (context)
7720        {
7721            if (context->getClientVersion() < 3)
7722            {
7723                return gl::error(GL_INVALID_OPERATION);
7724            }
7725
7726            if (program == 0)
7727            {
7728                return gl::error(GL_INVALID_VALUE);
7729            }
7730
7731            gl::Program *programObject = context->getProgram(program);
7732
7733            if (!programObject || !programObject->isLinked())
7734            {
7735                return gl::error(GL_INVALID_OPERATION);
7736            }
7737
7738            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
7739            if (!programBinary)
7740            {
7741                return gl::error(GL_INVALID_OPERATION);
7742            }
7743
7744            if (!programBinary->getUniformuiv(location, NULL, params))
7745            {
7746                return gl::error(GL_INVALID_OPERATION);
7747            }
7748        }
7749    }
7750    catch (...)
7751    {
7752        return gl::error(GL_OUT_OF_MEMORY);
7753    }
7754}
7755
7756GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name)
7757{
7758    EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
7759          program, name);
7760
7761    try
7762    {
7763        gl::Context *context = gl::getNonLostContext();
7764
7765        if (context)
7766        {
7767            if (context->getClientVersion() < 3)
7768            {
7769                return gl::error(GL_INVALID_OPERATION, -1);
7770            }
7771
7772            if (program == 0)
7773            {
7774                return gl::error(GL_INVALID_VALUE, -1);
7775            }
7776
7777            gl::Program *programObject = context->getProgram(program);
7778
7779            if (!programObject || !programObject->isLinked())
7780            {
7781                return gl::error(GL_INVALID_OPERATION, -1);
7782            }
7783
7784            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
7785            if (!programBinary)
7786            {
7787                return gl::error(GL_INVALID_OPERATION, -1);
7788            }
7789
7790            return programBinary->getFragDataLocation(name);
7791        }
7792    }
7793    catch (...)
7794    {
7795        return gl::error(GL_OUT_OF_MEMORY, 0);
7796    }
7797
7798    return 0;
7799}
7800
7801void __stdcall glUniform1ui(GLint location, GLuint v0)
7802{
7803    glUniform1uiv(location, 1, &v0);
7804}
7805
7806void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1)
7807{
7808    const GLuint xy[] = { v0, v1 };
7809    glUniform2uiv(location, 1, xy);
7810}
7811
7812void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
7813{
7814    const GLuint xyz[] = { v0, v1, v2 };
7815    glUniform3uiv(location, 1, xyz);
7816}
7817
7818void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
7819{
7820    const GLuint xyzw[] = { v0, v1, v2, v3 };
7821    glUniform4uiv(location, 1, xyzw);
7822}
7823
7824void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
7825{
7826    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
7827          location, count, value);
7828
7829    try
7830    {
7831        gl::Context *context = gl::getNonLostContext();
7832
7833        if (context)
7834        {
7835            if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
7836            {
7837                return;
7838            }
7839
7840            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
7841            programBinary->setUniform1uiv(location, count, value);
7842        }
7843    }
7844    catch (...)
7845    {
7846        return gl::error(GL_OUT_OF_MEMORY);
7847    }
7848}
7849
7850void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
7851{
7852    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
7853          location, count, value);
7854
7855    try
7856    {
7857        gl::Context *context = gl::getNonLostContext();
7858
7859        if (context)
7860        {
7861            if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
7862            {
7863                return;
7864            }
7865
7866            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
7867            programBinary->setUniform2uiv(location, count, value);
7868        }
7869    }
7870    catch (...)
7871    {
7872        return gl::error(GL_OUT_OF_MEMORY);
7873    }
7874}
7875
7876void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
7877{
7878    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
7879          location, count, value);
7880
7881    try
7882    {
7883        gl::Context *context = gl::getNonLostContext();
7884
7885        if (context)
7886        {
7887            if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
7888            {
7889                return;
7890            }
7891
7892            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
7893            programBinary->setUniform3uiv(location, count, value);
7894        }
7895    }
7896    catch (...)
7897    {
7898        return gl::error(GL_OUT_OF_MEMORY);
7899    }
7900}
7901
7902void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
7903{
7904    EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
7905          location, count, value);
7906
7907    try
7908    {
7909        gl::Context *context = gl::getNonLostContext();
7910
7911        if (context)
7912        {
7913            if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
7914            {
7915                return;
7916            }
7917
7918            gl::ProgramBinary *programBinary = context->getCurrentProgramBinary();
7919            programBinary->setUniform4uiv(location, count, value);
7920        }
7921    }
7922    catch (...)
7923    {
7924        return gl::error(GL_OUT_OF_MEMORY);
7925    }
7926}
7927
7928void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
7929{
7930    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
7931          buffer, drawbuffer, value);
7932
7933    try
7934    {
7935        gl::Context *context = gl::getNonLostContext();
7936
7937        if (context)
7938        {
7939            if (context->getClientVersion() < 3)
7940            {
7941                return gl::error(GL_INVALID_OPERATION);
7942            }
7943
7944            switch (buffer)
7945            {
7946              case GL_COLOR:
7947                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
7948                {
7949                    return gl::error(GL_INVALID_VALUE);
7950                }
7951                break;
7952              case GL_STENCIL:
7953                if (drawbuffer != 0)
7954                {
7955                    return gl::error(GL_INVALID_VALUE);
7956                }
7957                break;
7958              default:
7959                return gl::error(GL_INVALID_ENUM);
7960            }
7961
7962            context->clearBufferiv(buffer, drawbuffer, value);
7963        }
7964    }
7965    catch (...)
7966    {
7967        return gl::error(GL_OUT_OF_MEMORY);
7968    }
7969}
7970
7971void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
7972{
7973    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
7974          buffer, drawbuffer, value);
7975
7976    try
7977    {
7978        gl::Context *context = gl::getNonLostContext();
7979
7980        if (context)
7981        {
7982            if (context->getClientVersion() < 3)
7983            {
7984                return gl::error(GL_INVALID_OPERATION);
7985            }
7986
7987            switch (buffer)
7988            {
7989              case GL_COLOR:
7990                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
7991                {
7992                    return gl::error(GL_INVALID_VALUE);
7993                }
7994                break;
7995              default:
7996                return gl::error(GL_INVALID_ENUM);
7997            }
7998
7999            context->clearBufferuiv(buffer, drawbuffer, value);
8000        }
8001    }
8002    catch (...)
8003    {
8004        return gl::error(GL_OUT_OF_MEMORY);
8005    }
8006}
8007
8008void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
8009{
8010    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
8011          buffer, drawbuffer, value);
8012
8013    try
8014    {
8015        gl::Context *context = gl::getNonLostContext();
8016
8017        if (context)
8018        {
8019            if (context->getClientVersion() < 3)
8020            {
8021                return gl::error(GL_INVALID_OPERATION);
8022            }
8023
8024            switch (buffer)
8025            {
8026              case GL_COLOR:
8027                if (drawbuffer < 0 || drawbuffer >= static_cast<GLint>(context->getMaximumRenderTargets()))
8028                {
8029                    return gl::error(GL_INVALID_VALUE);
8030                }
8031                break;
8032              case GL_DEPTH:
8033                if (drawbuffer != 0)
8034                {
8035                    return gl::error(GL_INVALID_VALUE);
8036                }
8037                break;
8038              default:
8039                return gl::error(GL_INVALID_ENUM);
8040            }
8041
8042            context->clearBufferfv(buffer, drawbuffer, value);
8043        }
8044    }
8045    catch (...)
8046    {
8047        return gl::error(GL_OUT_OF_MEMORY);
8048    }
8049}
8050
8051void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
8052{
8053    EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
8054          buffer, drawbuffer, depth, stencil);
8055
8056    try
8057    {
8058        gl::Context *context = gl::getNonLostContext();
8059
8060        if (context)
8061        {
8062            if (context->getClientVersion() < 3)
8063            {
8064                return gl::error(GL_INVALID_OPERATION);
8065            }
8066
8067            switch (buffer)
8068            {
8069              case GL_DEPTH_STENCIL:
8070                if (drawbuffer != 0)
8071                {
8072                    return gl::error(GL_INVALID_VALUE);
8073                }
8074                break;
8075              default:
8076                return gl::error(GL_INVALID_ENUM);
8077            }
8078
8079            context->clearBufferfi(buffer, drawbuffer, depth, stencil);
8080        }
8081    }
8082    catch (...)
8083    {
8084        return gl::error(GL_OUT_OF_MEMORY);
8085    }
8086}
8087
8088const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index)
8089{
8090    EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
8091
8092    try
8093    {
8094        gl::Context *context = gl::getNonLostContext();
8095
8096        if (context)
8097        {
8098            if (context->getClientVersion() < 3)
8099            {
8100                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLubyte*>(NULL));
8101            }
8102
8103            if (name != GL_EXTENSIONS)
8104            {
8105                return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLubyte*>(NULL));
8106            }
8107
8108            if (index >= context->getNumExtensions())
8109            {
8110                return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLubyte*>(NULL));
8111            }
8112
8113            return reinterpret_cast<const GLubyte*>(context->getExtensionString(index));
8114        }
8115    }
8116    catch (...)
8117    {
8118        return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast<GLubyte*>(NULL));
8119    }
8120
8121    return NULL;
8122}
8123
8124void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
8125{
8126    EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
8127          readTarget, writeTarget, readOffset, writeOffset, size);
8128
8129    try
8130    {
8131        gl::Context *context = gl::getNonLostContext();
8132
8133        if (context)
8134        {
8135            if (context->getClientVersion() < 3)
8136            {
8137                return gl::error(GL_INVALID_OPERATION);
8138            }
8139
8140            if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget))
8141            {
8142                return gl::error(GL_INVALID_ENUM);
8143            }
8144
8145            gl::Buffer *readBuffer = context->getTargetBuffer(readTarget);
8146            gl::Buffer *writeBuffer = context->getTargetBuffer(writeTarget);
8147
8148            if (!readBuffer || !writeBuffer)
8149            {
8150                return gl::error(GL_INVALID_OPERATION);
8151            }
8152
8153            if (readBuffer->mapped() || writeBuffer->mapped())
8154            {
8155                return gl::error(GL_INVALID_OPERATION);
8156            }
8157
8158            if (readOffset < 0 || writeOffset < 0 || size < 0 ||
8159                static_cast<unsigned int>(readOffset + size) > readBuffer->size() ||
8160                static_cast<unsigned int>(writeOffset + size) > writeBuffer->size())
8161            {
8162                return gl::error(GL_INVALID_VALUE);
8163            }
8164
8165            if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size)
8166            {
8167                return gl::error(GL_INVALID_VALUE);
8168            }
8169
8170            // TODO: Verify that readBuffer and writeBuffer are not currently mapped (GL_INVALID_OPERATION)
8171
8172            // if size is zero, the copy is a successful no-op
8173            if (size > 0)
8174            {
8175                writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
8176            }
8177        }
8178    }
8179    catch (...)
8180    {
8181        return gl::error(GL_OUT_OF_MEMORY);
8182    }
8183}
8184
8185void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
8186{
8187    EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
8188          program, uniformCount, uniformNames, uniformIndices);
8189
8190    try
8191    {
8192        gl::Context *context = gl::getNonLostContext();
8193
8194        if (context)
8195        {
8196            if (context->getClientVersion() < 3)
8197            {
8198                return gl::error(GL_INVALID_OPERATION);
8199            }
8200
8201            if (uniformCount < 0)
8202            {
8203                return gl::error(GL_INVALID_VALUE);
8204            }
8205
8206            gl::Program *programObject = context->getProgram(program);
8207
8208            if (!programObject)
8209            {
8210                if (context->getShader(program))
8211                {
8212                    return gl::error(GL_INVALID_OPERATION);
8213                }
8214                else
8215                {
8216                    return gl::error(GL_INVALID_VALUE);
8217                }
8218            }
8219
8220            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8221            if (!programObject->isLinked() || !programBinary)
8222            {
8223                for (int uniformId = 0; uniformId < uniformCount; uniformId++)
8224                {
8225                    uniformIndices[uniformId] = GL_INVALID_INDEX;
8226                }
8227            }
8228            else
8229            {
8230                for (int uniformId = 0; uniformId < uniformCount; uniformId++)
8231                {
8232                    uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]);
8233                }
8234            }
8235        }
8236    }
8237    catch (...)
8238    {
8239        return gl::error(GL_OUT_OF_MEMORY);
8240    }
8241}
8242
8243void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
8244{
8245    EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
8246          program, uniformCount, uniformIndices, pname, params);
8247
8248    try
8249    {
8250        gl::Context *context = gl::getNonLostContext();
8251
8252        if (context)
8253        {
8254            if (context->getClientVersion() < 3)
8255            {
8256                return gl::error(GL_INVALID_OPERATION);
8257            }
8258
8259            if (uniformCount < 0)
8260            {
8261                return gl::error(GL_INVALID_VALUE);
8262            }
8263
8264            gl::Program *programObject = context->getProgram(program);
8265
8266            if (!programObject)
8267            {
8268                if (context->getShader(program))
8269                {
8270                    return gl::error(GL_INVALID_OPERATION);
8271                }
8272                else
8273                {
8274                    return gl::error(GL_INVALID_VALUE);
8275                }
8276            }
8277
8278            switch (pname)
8279            {
8280              case GL_UNIFORM_TYPE:
8281              case GL_UNIFORM_SIZE:
8282              case GL_UNIFORM_NAME_LENGTH:
8283              case GL_UNIFORM_BLOCK_INDEX:
8284              case GL_UNIFORM_OFFSET:
8285              case GL_UNIFORM_ARRAY_STRIDE:
8286              case GL_UNIFORM_MATRIX_STRIDE:
8287              case GL_UNIFORM_IS_ROW_MAJOR:
8288                break;
8289              default:
8290                return gl::error(GL_INVALID_ENUM);
8291            }
8292
8293            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8294
8295            if (!programBinary && uniformCount > 0)
8296            {
8297                return gl::error(GL_INVALID_VALUE);
8298            }
8299
8300            for (int uniformId = 0; uniformId < uniformCount; uniformId++)
8301            {
8302                const GLuint index = uniformIndices[uniformId];
8303
8304                if (index >= (GLuint)programBinary->getActiveUniformCount())
8305                {
8306                    return gl::error(GL_INVALID_VALUE);
8307                }
8308            }
8309
8310            for (int uniformId = 0; uniformId < uniformCount; uniformId++)
8311            {
8312                const GLuint index = uniformIndices[uniformId];
8313                params[uniformId] = programBinary->getActiveUniformi(index, pname);
8314            }
8315        }
8316    }
8317    catch (...)
8318    {
8319        return gl::error(GL_OUT_OF_MEMORY);
8320    }
8321}
8322
8323GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
8324{
8325    EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
8326
8327    try
8328    {
8329        gl::Context *context = gl::getNonLostContext();
8330
8331        if (context)
8332        {
8333            if (context->getClientVersion() < 3)
8334            {
8335                return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
8336            }
8337
8338            gl::Program *programObject = context->getProgram(program);
8339
8340            if (!programObject)
8341            {
8342                if (context->getShader(program))
8343                {
8344                    return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
8345                }
8346                else
8347                {
8348                    return gl::error(GL_INVALID_VALUE, GL_INVALID_INDEX);
8349                }
8350            }
8351
8352            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8353            if (!programBinary)
8354            {
8355                return GL_INVALID_INDEX;
8356            }
8357
8358            return programBinary->getUniformBlockIndex(uniformBlockName);
8359        }
8360    }
8361    catch (...)
8362    {
8363        return gl::error(GL_OUT_OF_MEMORY, 0);
8364    }
8365
8366    return 0;
8367}
8368
8369void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
8370{
8371    EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
8372          program, uniformBlockIndex, pname, params);
8373
8374    try
8375    {
8376        gl::Context *context = gl::getNonLostContext();
8377
8378        if (context)
8379        {
8380            if (context->getClientVersion() < 3)
8381            {
8382                return gl::error(GL_INVALID_OPERATION);
8383            }
8384            gl::Program *programObject = context->getProgram(program);
8385
8386            if (!programObject)
8387            {
8388                if (context->getShader(program))
8389                {
8390                    return gl::error(GL_INVALID_OPERATION);
8391                }
8392                else
8393                {
8394                    return gl::error(GL_INVALID_VALUE);
8395                }
8396            }
8397
8398            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8399
8400            if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
8401            {
8402                return gl::error(GL_INVALID_VALUE);
8403            }
8404
8405            switch (pname)
8406            {
8407              case GL_UNIFORM_BLOCK_BINDING:
8408                *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
8409                break;
8410
8411              case GL_UNIFORM_BLOCK_DATA_SIZE:
8412              case GL_UNIFORM_BLOCK_NAME_LENGTH:
8413              case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
8414              case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
8415              case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
8416              case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
8417                programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
8418                break;
8419
8420              default:
8421                return gl::error(GL_INVALID_ENUM);
8422            }
8423        }
8424    }
8425    catch (...)
8426    {
8427        return gl::error(GL_OUT_OF_MEMORY);
8428    }
8429}
8430
8431void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
8432{
8433    EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
8434          program, uniformBlockIndex, bufSize, length, uniformBlockName);
8435
8436    try
8437    {
8438        gl::Context *context = gl::getNonLostContext();
8439
8440        if (context)
8441        {
8442            if (context->getClientVersion() < 3)
8443            {
8444                return gl::error(GL_INVALID_OPERATION);
8445            }
8446
8447            gl::Program *programObject = context->getProgram(program);
8448
8449            if (!programObject)
8450            {
8451                if (context->getShader(program))
8452                {
8453                    return gl::error(GL_INVALID_OPERATION);
8454                }
8455                else
8456                {
8457                    return gl::error(GL_INVALID_VALUE);
8458                }
8459            }
8460
8461            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8462
8463            if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
8464            {
8465                return gl::error(GL_INVALID_VALUE);
8466            }
8467
8468            programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
8469        }
8470    }
8471    catch (...)
8472    {
8473        return gl::error(GL_OUT_OF_MEMORY);
8474    }
8475}
8476
8477void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
8478{
8479    EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
8480          program, uniformBlockIndex, uniformBlockBinding);
8481
8482    try
8483    {
8484        gl::Context *context = gl::getNonLostContext();
8485
8486        if (context)
8487        {
8488            if (context->getClientVersion() < 3)
8489            {
8490                return gl::error(GL_INVALID_OPERATION);
8491            }
8492
8493            if (uniformBlockBinding >= context->getMaximumCombinedUniformBufferBindings())
8494            {
8495                return gl::error(GL_INVALID_VALUE);
8496            }
8497
8498            gl::Program *programObject = context->getProgram(program);
8499
8500            if (!programObject)
8501            {
8502                if (context->getShader(program))
8503                {
8504                    return gl::error(GL_INVALID_OPERATION);
8505                }
8506                else
8507                {
8508                    return gl::error(GL_INVALID_VALUE);
8509                }
8510            }
8511
8512            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
8513
8514            // if never linked, there won't be any uniform blocks
8515            if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
8516            {
8517                return gl::error(GL_INVALID_VALUE);
8518            }
8519
8520            programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
8521        }
8522    }
8523    catch (...)
8524    {
8525        return gl::error(GL_OUT_OF_MEMORY);
8526    }
8527}
8528
8529void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
8530{
8531    EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
8532          mode, first, count, instanceCount);
8533
8534    try
8535    {
8536        gl::Context *context = gl::getNonLostContext();
8537
8538        if (context)
8539        {
8540            if (context->getClientVersion() < 3)
8541            {
8542                return gl::error(GL_INVALID_OPERATION);
8543            }
8544
8545            // glDrawArraysInstanced
8546            UNIMPLEMENTED();
8547        }
8548    }
8549    catch (...)
8550    {
8551        return gl::error(GL_OUT_OF_MEMORY);
8552    }
8553}
8554
8555void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
8556{
8557    EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
8558          mode, count, type, indices, instanceCount);
8559
8560    try
8561    {
8562        gl::Context *context = gl::getNonLostContext();
8563
8564        if (context)
8565        {
8566            if (context->getClientVersion() < 3)
8567            {
8568                return gl::error(GL_INVALID_OPERATION);
8569            }
8570
8571            // glDrawElementsInstanced
8572            UNIMPLEMENTED();
8573        }
8574    }
8575    catch (...)
8576    {
8577        return gl::error(GL_OUT_OF_MEMORY);
8578    }
8579}
8580
8581GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags)
8582{
8583    EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
8584
8585    try
8586    {
8587        gl::Context *context = gl::getNonLostContext();
8588
8589        if (context)
8590        {
8591            if (context->getClientVersion() < 3)
8592            {
8593                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLsync>(0));
8594            }
8595
8596            if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
8597            {
8598                return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLsync>(0));
8599            }
8600
8601            if (flags != 0)
8602            {
8603                return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLsync>(0));
8604            }
8605
8606            return context->createFenceSync(condition);
8607        }
8608    }
8609    catch (...)
8610    {
8611        return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast<GLsync>(NULL));
8612    }
8613
8614    return NULL;
8615}
8616
8617GLboolean __stdcall glIsSync(GLsync sync)
8618{
8619    EVENT("(GLsync sync = 0x%0.8p)", sync);
8620
8621    try
8622    {
8623        gl::Context *context = gl::getNonLostContext();
8624
8625        if (context)
8626        {
8627            if (context->getClientVersion() < 3)
8628            {
8629                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
8630            }
8631
8632            return (context->getFenceSync(sync) != NULL);
8633        }
8634    }
8635    catch (...)
8636    {
8637        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
8638    }
8639
8640    return GL_FALSE;
8641}
8642
8643void __stdcall glDeleteSync(GLsync sync)
8644{
8645    EVENT("(GLsync sync = 0x%0.8p)", sync);
8646
8647    try
8648    {
8649        gl::Context *context = gl::getNonLostContext();
8650
8651        if (context)
8652        {
8653            if (context->getClientVersion() < 3)
8654            {
8655                return gl::error(GL_INVALID_OPERATION);
8656            }
8657
8658            if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
8659            {
8660                return gl::error(GL_INVALID_VALUE);
8661            }
8662
8663            context->deleteFenceSync(sync);
8664        }
8665    }
8666    catch (...)
8667    {
8668        return gl::error(GL_OUT_OF_MEMORY);
8669    }
8670}
8671
8672GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
8673{
8674    EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
8675          sync, flags, timeout);
8676
8677    try
8678    {
8679        gl::Context *context = gl::getNonLostContext();
8680
8681        if (context)
8682        {
8683            if (context->getClientVersion() < 3)
8684            {
8685                return gl::error(GL_INVALID_OPERATION, GL_WAIT_FAILED);
8686            }
8687
8688            if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
8689            {
8690                return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED);
8691            }
8692
8693            gl::FenceSync *fenceSync = context->getFenceSync(sync);
8694
8695            if (!fenceSync)
8696            {
8697                return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED);
8698            }
8699
8700            return fenceSync->clientWait(flags, timeout);
8701        }
8702    }
8703    catch (...)
8704    {
8705        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
8706    }
8707
8708    return GL_FALSE;
8709}
8710
8711void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
8712{
8713    EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
8714          sync, flags, timeout);
8715
8716    try
8717    {
8718        gl::Context *context = gl::getNonLostContext();
8719
8720        if (context)
8721        {
8722            if (context->getClientVersion() < 3)
8723            {
8724                return gl::error(GL_INVALID_OPERATION);
8725            }
8726
8727            if (flags != 0)
8728            {
8729                return gl::error(GL_INVALID_VALUE);
8730            }
8731
8732            if (timeout != GL_TIMEOUT_IGNORED)
8733            {
8734                return gl::error(GL_INVALID_VALUE);
8735            }
8736
8737            gl::FenceSync *fenceSync = context->getFenceSync(sync);
8738
8739            if (!fenceSync)
8740            {
8741                return gl::error(GL_INVALID_VALUE);
8742            }
8743
8744            fenceSync->serverWait();
8745        }
8746    }
8747    catch (...)
8748    {
8749        return gl::error(GL_OUT_OF_MEMORY);
8750    }
8751}
8752
8753void __stdcall glGetInteger64v(GLenum pname, GLint64* params)
8754{
8755    EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
8756          pname, params);
8757
8758    try
8759    {
8760        gl::Context *context = gl::getNonLostContext();
8761
8762        if (context)
8763        {
8764            if (context->getClientVersion() < 3)
8765            {
8766                return gl::error(GL_INVALID_OPERATION);
8767            }
8768
8769            GLenum nativeType;
8770            unsigned int numParams = 0;
8771            if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
8772            {
8773                return;
8774            }
8775
8776            if (nativeType == GL_INT_64_ANGLEX)
8777            {
8778                context->getInteger64v(pname, params);
8779            }
8780            else
8781            {
8782                CastStateValues(context, nativeType, pname, numParams, params);
8783            }
8784        }
8785    }
8786    catch (...)
8787    {
8788        return gl::error(GL_OUT_OF_MEMORY);
8789    }
8790}
8791
8792void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
8793{
8794    EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
8795          sync, pname, bufSize, length, values);
8796
8797    try
8798    {
8799        gl::Context *context = gl::getNonLostContext();
8800
8801        if (context)
8802        {
8803            if (context->getClientVersion() < 3)
8804            {
8805                return gl::error(GL_INVALID_OPERATION);
8806            }
8807
8808            if (bufSize < 0)
8809            {
8810                return gl::error(GL_INVALID_VALUE);
8811            }
8812
8813            gl::FenceSync *fenceSync = context->getFenceSync(sync);
8814
8815            if (!fenceSync)
8816            {
8817                return gl::error(GL_INVALID_VALUE);
8818            }
8819
8820            switch (pname)
8821            {
8822              case GL_OBJECT_TYPE:     values[0] = static_cast<GLint>(GL_SYNC_FENCE);              break;
8823              case GL_SYNC_STATUS:     values[0] = static_cast<GLint>(fenceSync->getStatus());     break;
8824              case GL_SYNC_CONDITION:  values[0] = static_cast<GLint>(fenceSync->getCondition());  break;
8825              case GL_SYNC_FLAGS:      values[0] = 0;                                              break;
8826
8827              default:
8828                return gl::error(GL_INVALID_ENUM);
8829            }
8830        }
8831    }
8832    catch (...)
8833    {
8834        return gl::error(GL_OUT_OF_MEMORY);
8835    }
8836}
8837
8838void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
8839{
8840    EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
8841          target, index, data);
8842
8843    try
8844    {
8845        gl::Context *context = gl::getNonLostContext();
8846
8847        if (context)
8848        {
8849            if (context->getClientVersion() < 3)
8850            {
8851                return gl::error(GL_INVALID_OPERATION);
8852            }
8853
8854            switch (target)
8855            {
8856              case GL_TRANSFORM_FEEDBACK_BUFFER_START:
8857              case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
8858              case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
8859                if (index >= context->getMaxTransformFeedbackBufferBindings())
8860                    return gl::error(GL_INVALID_VALUE);
8861                break;
8862              case GL_UNIFORM_BUFFER_START:
8863              case GL_UNIFORM_BUFFER_SIZE:
8864              case GL_UNIFORM_BUFFER_BINDING:
8865                if (index >= context->getMaximumCombinedUniformBufferBindings())
8866                    return gl::error(GL_INVALID_VALUE);
8867                break;
8868              default:
8869                return gl::error(GL_INVALID_ENUM);
8870            }
8871
8872            if (!(context->getIndexedInteger64v(target, index, data)))
8873            {
8874                GLenum nativeType;
8875                unsigned int numParams = 0;
8876                if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
8877                    return gl::error(GL_INVALID_ENUM);
8878
8879                if (numParams == 0)
8880                    return; // it is known that pname is valid, but there are no parameters to return
8881
8882                if (nativeType == GL_INT)
8883                {
8884                    GLint *intParams = new GLint[numParams];
8885
8886                    context->getIndexedIntegerv(target, index, intParams);
8887
8888                    for (unsigned int i = 0; i < numParams; ++i)
8889                    {
8890                        data[i] = static_cast<GLint64>(intParams[i]);
8891                    }
8892
8893                    delete [] intParams;
8894                }
8895                else
8896                {
8897                    UNREACHABLE();
8898                }
8899            }
8900        }
8901    }
8902    catch (...)
8903    {
8904        return gl::error(GL_OUT_OF_MEMORY);
8905    }
8906}
8907
8908void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
8909{
8910    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
8911          target, pname, params);
8912
8913    try
8914    {
8915        gl::Context *context = gl::getNonLostContext();
8916
8917        if (context)
8918        {
8919            if (context->getClientVersion() < 3)
8920            {
8921                return gl::error(GL_INVALID_OPERATION);
8922            }
8923
8924            if (!gl::ValidBufferTarget(context, target))
8925            {
8926                return gl::error(GL_INVALID_ENUM);
8927            }
8928
8929            if (!gl::ValidBufferParameter(context, pname))
8930            {
8931                return gl::error(GL_INVALID_ENUM);
8932            }
8933
8934            gl::Buffer *buffer = context->getTargetBuffer(target);
8935
8936            if (!buffer)
8937            {
8938                // A null buffer means that "0" is bound to the requested buffer target
8939                return gl::error(GL_INVALID_OPERATION);
8940            }
8941
8942            switch (pname)
8943            {
8944              case GL_BUFFER_USAGE:
8945                *params = static_cast<GLint64>(buffer->usage());
8946                break;
8947              case GL_BUFFER_SIZE:
8948                *params = buffer->size();
8949                break;
8950              case GL_BUFFER_ACCESS_FLAGS:
8951                *params = static_cast<GLint64>(buffer->accessFlags());
8952                break;
8953              case GL_BUFFER_MAPPED:
8954                *params = static_cast<GLint64>(buffer->mapped());
8955                break;
8956              case GL_BUFFER_MAP_OFFSET:
8957                *params = buffer->mapOffset();
8958                break;
8959              case GL_BUFFER_MAP_LENGTH:
8960                *params = buffer->mapLength();
8961                break;
8962              default: UNREACHABLE(); break;
8963            }
8964        }
8965    }
8966    catch (...)
8967    {
8968        return gl::error(GL_OUT_OF_MEMORY);
8969    }
8970}
8971
8972void __stdcall glGenSamplers(GLsizei count, GLuint* samplers)
8973{
8974    EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
8975
8976    try
8977    {
8978        gl::Context *context = gl::getNonLostContext();
8979
8980        if (context)
8981        {
8982            if (context->getClientVersion() < 3)
8983            {
8984                return gl::error(GL_INVALID_OPERATION);
8985            }
8986
8987            if (count < 0)
8988            {
8989                return gl::error(GL_INVALID_VALUE);
8990            }
8991
8992            for (int i = 0; i < count; i++)
8993            {
8994                samplers[i] = context->createSampler();
8995            }
8996        }
8997    }
8998    catch (...)
8999    {
9000        return gl::error(GL_OUT_OF_MEMORY);
9001    }
9002}
9003
9004void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers)
9005{
9006    EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
9007
9008    try
9009    {
9010        gl::Context *context = gl::getNonLostContext();
9011
9012        if (context)
9013        {
9014            if (context->getClientVersion() < 3)
9015            {
9016                return gl::error(GL_INVALID_OPERATION);
9017            }
9018
9019            if (count < 0)
9020            {
9021                return gl::error(GL_INVALID_VALUE);
9022            }
9023
9024            for (int i = 0; i < count; i++)
9025            {
9026                context->deleteSampler(samplers[i]);
9027            }
9028        }
9029    }
9030    catch (...)
9031    {
9032        return gl::error(GL_OUT_OF_MEMORY);
9033    }
9034}
9035
9036GLboolean __stdcall glIsSampler(GLuint sampler)
9037{
9038    EVENT("(GLuint sampler = %u)", sampler);
9039
9040    try
9041    {
9042        gl::Context *context = gl::getNonLostContext();
9043
9044        if (context)
9045        {
9046            if (context->getClientVersion() < 3)
9047            {
9048                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
9049            }
9050
9051            return context->isSampler(sampler);
9052        }
9053    }
9054    catch (...)
9055    {
9056        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
9057    }
9058
9059    return GL_FALSE;
9060}
9061
9062void __stdcall glBindSampler(GLuint unit, GLuint sampler)
9063{
9064    EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
9065
9066    try
9067    {
9068        gl::Context *context = gl::getNonLostContext();
9069
9070        if (context)
9071        {
9072            if (context->getClientVersion() < 3)
9073            {
9074                return gl::error(GL_INVALID_OPERATION);
9075            }
9076
9077            if (sampler != 0 && !context->isSampler(sampler))
9078            {
9079                return gl::error(GL_INVALID_OPERATION);
9080            }
9081
9082            if (unit >= context->getMaximumCombinedTextureImageUnits())
9083            {
9084                return gl::error(GL_INVALID_VALUE);
9085            }
9086
9087            context->bindSampler(unit, sampler);
9088        }
9089    }
9090    catch (...)
9091    {
9092        return gl::error(GL_OUT_OF_MEMORY);
9093    }
9094}
9095
9096void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
9097{
9098    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
9099
9100    try
9101    {
9102        gl::Context *context = gl::getNonLostContext();
9103
9104        if (context)
9105        {
9106            if (context->getClientVersion() < 3)
9107            {
9108                return gl::error(GL_INVALID_OPERATION);
9109            }
9110
9111            if (!gl::ValidateSamplerObjectParameter(pname))
9112            {
9113                return;
9114            }
9115
9116            if (!gl::ValidateTexParamParameters(context, pname, param))
9117            {
9118                return;
9119            }
9120
9121            if (!context->isSampler(sampler))
9122            {
9123                return gl::error(GL_INVALID_OPERATION);
9124            }
9125
9126            context->samplerParameteri(sampler, pname, param);
9127        }
9128    }
9129    catch (...)
9130    {
9131        return gl::error(GL_OUT_OF_MEMORY);
9132    }
9133}
9134
9135void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
9136{
9137    glSamplerParameteri(sampler, pname, *param);
9138}
9139
9140void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
9141{
9142    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
9143
9144    try
9145    {
9146        gl::Context *context = gl::getNonLostContext();
9147
9148        if (context)
9149        {
9150            if (context->getClientVersion() < 3)
9151            {
9152                return gl::error(GL_INVALID_OPERATION);
9153            }
9154
9155            if (!gl::ValidateSamplerObjectParameter(pname))
9156            {
9157                return;
9158            }
9159
9160            if (!gl::ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
9161            {
9162                return;
9163            }
9164
9165            if (!context->isSampler(sampler))
9166            {
9167                return gl::error(GL_INVALID_OPERATION);
9168            }
9169
9170            context->samplerParameterf(sampler, pname, param);
9171        }
9172    }
9173    catch (...)
9174    {
9175        return gl::error(GL_OUT_OF_MEMORY);
9176    }
9177}
9178
9179void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
9180{
9181    glSamplerParameterf(sampler, pname, *param);
9182}
9183
9184void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
9185{
9186    EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
9187
9188    try
9189    {
9190        gl::Context *context = gl::getNonLostContext();
9191
9192        if (context)
9193        {
9194            if (context->getClientVersion() < 3)
9195            {
9196                return gl::error(GL_INVALID_OPERATION);
9197            }
9198
9199            if (!gl::ValidateSamplerObjectParameter(pname))
9200            {
9201                return;
9202            }
9203
9204            if (!context->isSampler(sampler))
9205            {
9206                return gl::error(GL_INVALID_OPERATION);
9207            }
9208
9209            *params = context->getSamplerParameteri(sampler, pname);
9210        }
9211    }
9212    catch (...)
9213    {
9214        return gl::error(GL_OUT_OF_MEMORY);
9215    }
9216}
9217
9218void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
9219{
9220    EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
9221
9222    try
9223    {
9224        gl::Context *context = gl::getNonLostContext();
9225
9226        if (context)
9227        {
9228            if (context->getClientVersion() < 3)
9229            {
9230                return gl::error(GL_INVALID_OPERATION);
9231            }
9232
9233            if (!gl::ValidateSamplerObjectParameter(pname))
9234            {
9235                return;
9236            }
9237
9238            if (!context->isSampler(sampler))
9239            {
9240                return gl::error(GL_INVALID_OPERATION);
9241            }
9242
9243            *params = context->getSamplerParameterf(sampler, pname);
9244        }
9245    }
9246    catch (...)
9247    {
9248        return gl::error(GL_OUT_OF_MEMORY);
9249    }
9250}
9251
9252void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor)
9253{
9254    EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
9255
9256    try
9257    {
9258        if (index >= gl::MAX_VERTEX_ATTRIBS)
9259        {
9260            return gl::error(GL_INVALID_VALUE);
9261        }
9262
9263        gl::Context *context = gl::getNonLostContext();
9264
9265        if (context)
9266        {
9267            if (context->getClientVersion() < 3)
9268            {
9269                return gl::error(GL_INVALID_OPERATION);
9270            }
9271
9272            context->setVertexAttribDivisor(index, divisor);
9273        }
9274    }
9275    catch (...)
9276    {
9277        return gl::error(GL_OUT_OF_MEMORY);
9278    }
9279}
9280
9281void __stdcall glBindTransformFeedback(GLenum target, GLuint id)
9282{
9283    EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
9284
9285    try
9286    {
9287        gl::Context *context = gl::getNonLostContext();
9288
9289        if (context)
9290        {
9291            if (context->getClientVersion() < 3)
9292            {
9293                return gl::error(GL_INVALID_OPERATION);
9294            }
9295
9296            switch (target)
9297            {
9298              case GL_TRANSFORM_FEEDBACK:
9299                {
9300                    // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
9301                    gl::TransformFeedback *curTransformFeedback = context->getCurrentTransformFeedback();
9302                    if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
9303                    {
9304                        return gl::error(GL_INVALID_OPERATION);
9305                    }
9306
9307                    // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
9308                    if (context->getTransformFeedback(id) == NULL)
9309                    {
9310                        return gl::error(GL_INVALID_OPERATION);
9311                    }
9312
9313                    context->bindTransformFeedback(id);
9314                }
9315                break;
9316
9317              default:
9318                return gl::error(GL_INVALID_ENUM);
9319            }
9320        }
9321    }
9322    catch (...)
9323    {
9324        return gl::error(GL_OUT_OF_MEMORY);
9325    }
9326}
9327
9328void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
9329{
9330    EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
9331
9332    try
9333    {
9334        gl::Context *context = gl::getNonLostContext();
9335
9336        if (context)
9337        {
9338            if (context->getClientVersion() < 3)
9339            {
9340                return gl::error(GL_INVALID_OPERATION);
9341            }
9342
9343            for (int i = 0; i < n; i++)
9344            {
9345                context->deleteTransformFeedback(ids[i]);
9346            }
9347        }
9348    }
9349    catch (...)
9350    {
9351        return gl::error(GL_OUT_OF_MEMORY);
9352    }
9353}
9354
9355void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids)
9356{
9357    EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
9358
9359    try
9360    {
9361        gl::Context *context = gl::getNonLostContext();
9362
9363        if (context)
9364        {
9365            if (context->getClientVersion() < 3)
9366            {
9367                return gl::error(GL_INVALID_OPERATION);
9368            }
9369
9370            for (int i = 0; i < n; i++)
9371            {
9372                ids[i] = context->createTransformFeedback();
9373            }
9374        }
9375    }
9376    catch (...)
9377    {
9378        return gl::error(GL_OUT_OF_MEMORY);
9379    }
9380}
9381
9382GLboolean __stdcall glIsTransformFeedback(GLuint id)
9383{
9384    EVENT("(GLuint id = %u)", id);
9385
9386    try
9387    {
9388        gl::Context *context = gl::getNonLostContext();
9389
9390        if (context)
9391        {
9392            if (context->getClientVersion() < 3)
9393            {
9394                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
9395            }
9396
9397            return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE);
9398        }
9399    }
9400    catch (...)
9401    {
9402        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
9403    }
9404
9405    return GL_FALSE;
9406}
9407
9408void __stdcall glPauseTransformFeedback(void)
9409{
9410    EVENT("(void)");
9411
9412    try
9413    {
9414        gl::Context *context = gl::getNonLostContext();
9415
9416        if (context)
9417        {
9418            if (context->getClientVersion() < 3)
9419            {
9420                return gl::error(GL_INVALID_OPERATION);
9421            }
9422
9423            gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback();
9424            ASSERT(transformFeedback != NULL);
9425
9426            // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86)
9427            if (!transformFeedback->isStarted() || transformFeedback->isPaused())
9428            {
9429                return gl::error(GL_INVALID_OPERATION);
9430            }
9431
9432            transformFeedback->pause();
9433        }
9434    }
9435    catch (...)
9436    {
9437        return gl::error(GL_OUT_OF_MEMORY);
9438    }
9439}
9440
9441void __stdcall glResumeTransformFeedback(void)
9442{
9443    EVENT("(void)");
9444
9445    try
9446    {
9447        gl::Context *context = gl::getNonLostContext();
9448
9449        if (context)
9450        {
9451            if (context->getClientVersion() < 3)
9452            {
9453                return gl::error(GL_INVALID_OPERATION);
9454            }
9455
9456            gl::TransformFeedback *transformFeedback = context->getCurrentTransformFeedback();
9457            ASSERT(transformFeedback != NULL);
9458
9459            // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86)
9460            if (!transformFeedback->isStarted() || !transformFeedback->isPaused())
9461            {
9462                return gl::error(GL_INVALID_OPERATION);
9463            }
9464
9465            transformFeedback->resume();
9466        }
9467    }
9468    catch (...)
9469    {
9470        return gl::error(GL_OUT_OF_MEMORY);
9471    }
9472}
9473
9474void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
9475{
9476    EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
9477          program, bufSize, length, binaryFormat, binary);
9478
9479    try
9480    {
9481        gl::Context *context = gl::getNonLostContext();
9482
9483        if (context)
9484        {
9485            if (context->getClientVersion() < 3)
9486            {
9487                return gl::error(GL_INVALID_OPERATION);
9488            }
9489
9490            // glGetProgramBinary
9491            UNIMPLEMENTED();
9492        }
9493    }
9494    catch (...)
9495    {
9496        return gl::error(GL_OUT_OF_MEMORY);
9497    }
9498}
9499
9500void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
9501{
9502    EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
9503          program, binaryFormat, binary, length);
9504
9505    try
9506    {
9507        gl::Context *context = gl::getNonLostContext();
9508
9509        if (context)
9510        {
9511            if (context->getClientVersion() < 3)
9512            {
9513                return gl::error(GL_INVALID_OPERATION);
9514            }
9515
9516            // glProgramBinary
9517            UNIMPLEMENTED();
9518        }
9519    }
9520    catch (...)
9521    {
9522        return gl::error(GL_OUT_OF_MEMORY);
9523    }
9524}
9525
9526void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value)
9527{
9528    EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
9529          program, pname, value);
9530
9531    try
9532    {
9533        gl::Context *context = gl::getNonLostContext();
9534
9535        if (context)
9536        {
9537            if (context->getClientVersion() < 3)
9538            {
9539                return gl::error(GL_INVALID_OPERATION);
9540            }
9541
9542            // glProgramParameteri
9543            UNIMPLEMENTED();
9544        }
9545    }
9546    catch (...)
9547    {
9548        return gl::error(GL_OUT_OF_MEMORY);
9549    }
9550}
9551
9552void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
9553{
9554    EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
9555          target, numAttachments, attachments);
9556
9557    try
9558    {
9559        gl::Context *context = gl::getNonLostContext();
9560
9561        if (context)
9562        {
9563            if (context->getClientVersion() < 3)
9564            {
9565                return gl::error(GL_INVALID_OPERATION);
9566            }
9567
9568            if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
9569            {
9570                return;
9571            }
9572
9573            int maxDimension = context->getMaximumRenderbufferDimension();
9574            context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
9575        }
9576    }
9577    catch (...)
9578    {
9579        return gl::error(GL_OUT_OF_MEMORY);
9580    }
9581}
9582
9583void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
9584{
9585    EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
9586          "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
9587          target, numAttachments, attachments, x, y, width, height);
9588
9589    try
9590    {
9591        gl::Context *context = gl::getNonLostContext();
9592
9593        if (context)
9594        {
9595            if (context->getClientVersion() < 3)
9596            {
9597                return gl::error(GL_INVALID_OPERATION);
9598            }
9599
9600            if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
9601            {
9602                return;
9603            }
9604
9605            context->invalidateFrameBuffer(target, numAttachments, attachments, x, y, width, height);
9606        }
9607    }
9608    catch (...)
9609    {
9610        return gl::error(GL_OUT_OF_MEMORY);
9611    }
9612}
9613
9614void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
9615{
9616    EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
9617          target, levels, internalformat, width, height);
9618
9619    try
9620    {
9621        gl::Context *context = gl::getNonLostContext();
9622
9623        if (context)
9624        {
9625            if (context->getClientVersion() < 3)
9626            {
9627                return gl::error(GL_INVALID_OPERATION);
9628            }
9629
9630            if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
9631            {
9632                return;
9633            }
9634
9635            switch (target)
9636            {
9637              case GL_TEXTURE_2D:
9638                {
9639                    gl::Texture2D *texture2d = context->getTexture2D();
9640                    texture2d->storage(levels, internalformat, width, height);
9641                }
9642                break;
9643
9644              case GL_TEXTURE_CUBE_MAP:
9645                {
9646                    gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
9647                    textureCube->storage(levels, internalformat, width);
9648                }
9649                break;
9650
9651              default:
9652                return gl::error(GL_INVALID_ENUM);
9653            }
9654        }
9655    }
9656    catch (...)
9657    {
9658        return gl::error(GL_OUT_OF_MEMORY);
9659    }
9660}
9661
9662void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
9663{
9664    EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
9665          "GLsizei height = %d, GLsizei depth = %d)",
9666          target, levels, internalformat, width, height, depth);
9667
9668    try
9669    {
9670        gl::Context *context = gl::getNonLostContext();
9671
9672        if (context)
9673        {
9674            if (context->getClientVersion() < 3)
9675            {
9676                return gl::error(GL_INVALID_OPERATION);
9677            }
9678
9679            if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
9680            {
9681                return;
9682            }
9683
9684            switch (target)
9685            {
9686              case GL_TEXTURE_3D:
9687                {
9688                    gl::Texture3D *texture3d = context->getTexture3D();
9689                    texture3d->storage(levels, internalformat, width, height, depth);
9690                }
9691                break;
9692
9693              case GL_TEXTURE_2D_ARRAY:
9694                {
9695                    gl::Texture2DArray *texture2darray = context->getTexture2DArray();
9696                    texture2darray->storage(levels, internalformat, width, height, depth);
9697                }
9698                break;
9699
9700              default:
9701                UNREACHABLE();
9702            }
9703        }
9704    }
9705    catch (...)
9706    {
9707        return gl::error(GL_OUT_OF_MEMORY);
9708    }
9709}
9710
9711void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
9712{
9713    EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
9714          "GLint* params = 0x%0.8p)",
9715          target, internalformat, pname, bufSize, params);
9716
9717    try
9718    {
9719        gl::Context *context = gl::getNonLostContext();
9720
9721        if (context)
9722        {
9723            if (context->getClientVersion() < 3)
9724            {
9725                return gl::error(GL_INVALID_OPERATION);
9726            }
9727
9728            if (!gl::IsColorRenderingSupported(internalformat, context) &&
9729                !gl::IsDepthRenderingSupported(internalformat, context) &&
9730                !gl::IsStencilRenderingSupported(internalformat, context))
9731            {
9732                return gl::error(GL_INVALID_ENUM);
9733            }
9734
9735            if (target != GL_RENDERBUFFER)
9736            {
9737                return gl::error(GL_INVALID_ENUM);
9738            }
9739
9740            if (bufSize < 0)
9741            {
9742                return gl::error(GL_INVALID_VALUE);
9743            }
9744
9745            switch (pname)
9746            {
9747              case GL_NUM_SAMPLE_COUNTS:
9748                if (bufSize != 0)
9749                    *params = context->getNumSampleCounts(internalformat);
9750                break;
9751              case GL_SAMPLES:
9752                context->getSampleCounts(internalformat, bufSize, params);
9753                break;
9754              default:
9755                return gl::error(GL_INVALID_ENUM);
9756            }
9757        }
9758    }
9759    catch (...)
9760    {
9761        return gl::error(GL_OUT_OF_MEMORY);
9762    }
9763}
9764
9765// Extension functions
9766
9767void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
9768                                      GLbitfield mask, GLenum filter)
9769{
9770    EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
9771          "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
9772          "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
9773          srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
9774
9775    try
9776    {
9777        gl::Context *context = gl::getNonLostContext();
9778
9779        if (context)
9780        {
9781            if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
9782                                                   dstX0, dstY0, dstX1, dstY1, mask, filter,
9783                                                   true))
9784            {
9785                return;
9786            }
9787
9788            context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
9789                                     mask, filter);
9790        }
9791    }
9792    catch (...)
9793    {
9794        return gl::error(GL_OUT_OF_MEMORY);
9795    }
9796}
9797
9798void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
9799                               GLint border, GLenum format, GLenum type, const GLvoid* pixels)
9800{
9801    EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
9802          "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
9803          "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
9804          target, level, internalformat, width, height, depth, border, format, type, pixels);
9805
9806    try
9807    {
9808        UNIMPLEMENTED();   // FIXME
9809    }
9810    catch (...)
9811    {
9812        return gl::error(GL_OUT_OF_MEMORY);
9813    }
9814}
9815
9816void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
9817                                     GLenum *binaryFormat, void *binary)
9818{
9819    EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
9820          program, bufSize, length, binaryFormat, binary);
9821
9822    try
9823    {
9824        gl::Context *context = gl::getNonLostContext();
9825
9826        if (context)
9827        {
9828            gl::Program *programObject = context->getProgram(program);
9829
9830            if (!programObject || !programObject->isLinked())
9831            {
9832                return gl::error(GL_INVALID_OPERATION);
9833            }
9834
9835            gl::ProgramBinary *programBinary = programObject->getProgramBinary();
9836
9837            if (!programBinary)
9838            {
9839                return gl::error(GL_INVALID_OPERATION);
9840            }
9841
9842            if (!programBinary->save(binary, bufSize, length))
9843            {
9844                return gl::error(GL_INVALID_OPERATION);
9845            }
9846
9847            *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
9848        }
9849    }
9850    catch (...)
9851    {
9852        return gl::error(GL_OUT_OF_MEMORY);
9853    }
9854}
9855
9856void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat,
9857                                  const void *binary, GLint length)
9858{
9859    EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
9860          program, binaryFormat, binary, length);
9861
9862    try
9863    {
9864        gl::Context *context = gl::getNonLostContext();
9865
9866        if (context)
9867        {
9868            if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
9869            {
9870                return gl::error(GL_INVALID_ENUM);
9871            }
9872
9873            gl::Program *programObject = context->getProgram(program);
9874
9875            if (!programObject)
9876            {
9877                return gl::error(GL_INVALID_OPERATION);
9878            }
9879
9880            context->setProgramBinary(program, binary, length);
9881        }
9882    }
9883    catch (...)
9884    {
9885        return gl::error(GL_OUT_OF_MEMORY);
9886    }
9887}
9888
9889void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
9890{
9891    EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
9892
9893    try
9894    {
9895        gl::Context *context = gl::getNonLostContext();
9896
9897        if (context)
9898        {
9899            if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets())
9900            {
9901                return gl::error(GL_INVALID_VALUE);
9902            }
9903
9904            if (context->getDrawFramebufferHandle() == 0)
9905            {
9906                if (n != 1)
9907                {
9908                    return gl::error(GL_INVALID_OPERATION);
9909                }
9910
9911                if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
9912                {
9913                    return gl::error(GL_INVALID_OPERATION);
9914                }
9915            }
9916            else
9917            {
9918                for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
9919                {
9920                    const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
9921                    if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
9922                    {
9923                        return gl::error(GL_INVALID_OPERATION);
9924                    }
9925                }
9926            }
9927
9928            gl::Framebuffer *framebuffer = context->getDrawFramebuffer();
9929
9930            for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
9931            {
9932                framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
9933            }
9934
9935            for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++)
9936            {
9937                framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
9938            }
9939        }
9940    }
9941    catch (...)
9942    {
9943        return gl::error(GL_OUT_OF_MEMORY);
9944    }
9945}
9946
9947void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params)
9948{
9949    EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
9950
9951    try
9952    {
9953        gl::Context *context = gl::getNonLostContext();
9954
9955        if (context)
9956        {
9957            if (!context->supportsPBOs())
9958            {
9959                return gl::error(GL_INVALID_OPERATION);
9960            }
9961
9962            if (!gl::ValidBufferTarget(context, target))
9963            {
9964                return gl::error(GL_INVALID_ENUM);
9965            }
9966
9967            if (pname != GL_BUFFER_MAP_POINTER)
9968            {
9969                return gl::error(GL_INVALID_ENUM);
9970            }
9971
9972            gl::Buffer *buffer = context->getTargetBuffer(target);
9973
9974            if (!buffer || !buffer->mapped())
9975            {
9976                *params = NULL;
9977            }
9978
9979            *params = buffer->mapPointer();
9980        }
9981    }
9982    catch (...)
9983    {
9984        return gl::error(GL_OUT_OF_MEMORY);
9985    }
9986}
9987
9988void * __stdcall glMapBufferOES(GLenum target, GLenum access)
9989{
9990    EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
9991
9992    try
9993    {
9994        gl::Context *context = gl::getNonLostContext();
9995
9996        if (context)
9997        {
9998            if (!gl::ValidBufferTarget(context, target))
9999            {
10000                return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL));
10001            }
10002
10003            gl::Buffer *buffer = context->getTargetBuffer(target);
10004
10005            if (buffer == NULL)
10006            {
10007                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10008            }
10009
10010            if (access != GL_WRITE_ONLY_OES)
10011            {
10012                return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL));
10013            }
10014
10015            if (buffer->mapped())
10016            {
10017                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10018            }
10019
10020            return buffer->mapRange(0, buffer->size(), GL_MAP_WRITE_BIT);
10021        }
10022    }
10023    catch (...)
10024    {
10025        return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast<GLvoid*>(NULL));
10026    }
10027
10028    return NULL;
10029}
10030
10031GLboolean __stdcall glUnmapBufferOES(GLenum target)
10032{
10033    EVENT("(GLenum target = 0x%X)", target);
10034
10035    try
10036    {
10037        gl::Context *context = gl::getNonLostContext();
10038
10039        if (context)
10040        {
10041            if (!gl::ValidBufferTarget(context, target))
10042            {
10043                return gl::error(GL_INVALID_ENUM, GL_FALSE);
10044            }
10045
10046            gl::Buffer *buffer = context->getTargetBuffer(target);
10047
10048            if (buffer == NULL || !buffer->mapped())
10049            {
10050                return gl::error(GL_INVALID_OPERATION, GL_FALSE);
10051            }
10052
10053            // TODO: detect if we had corruption. if so, throw an error and return false.
10054
10055            buffer->unmap();
10056
10057            return GL_TRUE;
10058        }
10059    }
10060    catch (...)
10061    {
10062        return gl::error(GL_OUT_OF_MEMORY, GL_FALSE);
10063    }
10064
10065    return GL_FALSE;
10066}
10067
10068void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
10069{
10070    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
10071          target, offset, length, access);
10072
10073    try
10074    {
10075        gl::Context *context = gl::getNonLostContext();
10076
10077        if (context)
10078        {
10079            if (!gl::ValidBufferTarget(context, target))
10080            {
10081                return gl::error(GL_INVALID_ENUM, reinterpret_cast<GLvoid*>(NULL));
10082            }
10083
10084            if (offset < 0 || length < 0)
10085            {
10086                return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL));
10087            }
10088
10089            gl::Buffer *buffer = context->getTargetBuffer(target);
10090
10091            if (buffer == NULL)
10092            {
10093                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10094            }
10095
10096            // Check for buffer overflow
10097            size_t offsetSize = static_cast<size_t>(offset);
10098            size_t lengthSize = static_cast<size_t>(length);
10099
10100            if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
10101                offsetSize + lengthSize > static_cast<size_t>(buffer->size()))
10102            {
10103                return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL));
10104            }
10105
10106            // Check for invalid bits in the mask
10107            GLbitfield allAccessBits = GL_MAP_READ_BIT |
10108                                       GL_MAP_WRITE_BIT |
10109                                       GL_MAP_INVALIDATE_RANGE_BIT |
10110                                       GL_MAP_INVALIDATE_BUFFER_BIT |
10111                                       GL_MAP_FLUSH_EXPLICIT_BIT |
10112                                       GL_MAP_UNSYNCHRONIZED_BIT;
10113
10114            if (access & ~(allAccessBits))
10115            {
10116                return gl::error(GL_INVALID_VALUE, reinterpret_cast<GLvoid*>(NULL));
10117            }
10118
10119            if (length == 0 || buffer->mapped())
10120            {
10121                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10122            }
10123
10124            // Check for invalid bit combinations
10125            if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
10126            {
10127                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10128            }
10129
10130            GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT |
10131                                       GL_MAP_INVALIDATE_BUFFER_BIT |
10132                                       GL_MAP_UNSYNCHRONIZED_BIT;
10133
10134            if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
10135            {
10136                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10137            }
10138
10139            if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
10140            {
10141                return gl::error(GL_INVALID_OPERATION, reinterpret_cast<GLvoid*>(NULL));
10142            }
10143
10144            return buffer->mapRange(offset, length, access);
10145        }
10146    }
10147    catch (...)
10148    {
10149        return gl::error(GL_OUT_OF_MEMORY, reinterpret_cast<GLvoid*>(NULL));
10150    }
10151
10152    return NULL;
10153}
10154
10155void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length)
10156{
10157    EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
10158
10159    try
10160    {
10161        gl::Context *context = gl::getNonLostContext();
10162
10163        if (context)
10164        {
10165            if (offset < 0 || length < 0)
10166            {
10167                return gl::error(GL_INVALID_VALUE);
10168            }
10169
10170            if (!gl::ValidBufferTarget(context, target))
10171            {
10172                return gl::error(GL_INVALID_ENUM);
10173            }
10174
10175            gl::Buffer *buffer = context->getTargetBuffer(target);
10176
10177            if (buffer == NULL)
10178            {
10179                return gl::error(GL_INVALID_OPERATION);
10180            }
10181
10182            if (!buffer->mapped() || (buffer->accessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
10183            {
10184                return gl::error(GL_INVALID_OPERATION);
10185            }
10186
10187            // Check for buffer overflow
10188            size_t offsetSize = static_cast<size_t>(offset);
10189            size_t lengthSize = static_cast<size_t>(length);
10190
10191            if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
10192                offsetSize + lengthSize > static_cast<size_t>(buffer->mapLength()))
10193            {
10194                return gl::error(GL_INVALID_VALUE);
10195            }
10196
10197            // We do not currently support a non-trivial implementation of FlushMappedBufferRange
10198        }
10199    }
10200    catch (...)
10201    {
10202        return gl::error(GL_OUT_OF_MEMORY);
10203    }
10204}
10205
10206__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname)
10207{
10208    struct Extension
10209    {
10210        const char *name;
10211        __eglMustCastToProperFunctionPointerType address;
10212    };
10213
10214    static const Extension glExtensions[] =
10215    {
10216        {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
10217        {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
10218        {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},
10219        {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},
10220        {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},
10221        {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},
10222        {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},
10223        {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
10224        {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
10225        {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
10226        {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
10227        {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT},
10228        {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},
10229        {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},
10230        {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},
10231        {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},
10232        {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},
10233        {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},
10234        {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},
10235        {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},
10236        {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},
10237        {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},
10238        {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},
10239        {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT},
10240        {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE},
10241        {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
10242        {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
10243        {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES},
10244        {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES},
10245        {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES},
10246        {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES},
10247        {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES},
10248        {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT},
10249        {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT},    };
10250
10251    for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++)
10252    {
10253        if (strcmp(procname, glExtensions[ext].name) == 0)
10254        {
10255            return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
10256        }
10257    }
10258
10259    return NULL;
10260}
10261
10262// Non-public functions used by EGL
10263
10264bool __stdcall glBindTexImage(egl::Surface *surface)
10265{
10266    EVENT("(egl::Surface* surface = 0x%0.8p)",
10267          surface);
10268
10269    try
10270    {
10271        gl::Context *context = gl::getNonLostContext();
10272
10273        if (context)
10274        {
10275            gl::Texture2D *textureObject = context->getTexture2D();
10276            ASSERT(textureObject != NULL);
10277
10278            if (textureObject->isImmutable())
10279            {
10280                return false;
10281            }
10282
10283            textureObject->bindTexImage(surface);
10284        }
10285    }
10286    catch (...)
10287    {
10288        return gl::error(GL_OUT_OF_MEMORY, false);
10289    }
10290
10291    return true;
10292}
10293
10294}
10295