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