1 //
2 // Copyright(c) 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 // entry_points_gles_2_0.cpp : Implements the GLES 2.0 entry points.
8 
9 #include "libGLESv2/entry_points_gles_2_0.h"
10 
11 #include "libGLESv2/global_state.h"
12 
13 #include "libANGLE/formatutils.h"
14 #include "libANGLE/Buffer.h"
15 #include "libANGLE/Compiler.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Error.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/Renderbuffer.h"
20 #include "libANGLE/Shader.h"
21 #include "libANGLE/Program.h"
22 #include "libANGLE/Texture.h"
23 #include "libANGLE/VertexArray.h"
24 #include "libANGLE/VertexAttribute.h"
25 #include "libANGLE/FramebufferAttachment.h"
26 
27 #include "libANGLE/validationES.h"
28 #include "libANGLE/validationES2.h"
29 #include "libANGLE/validationES3.h"
30 #include "libANGLE/queryconversions.h"
31 #include "libANGLE/queryutils.h"
32 
33 #include "common/debug.h"
34 #include "common/utilities.h"
35 #include "common/version.h"
36 
37 namespace gl
38 {
39 
ActiveTexture(GLenum texture)40 void GL_APIENTRY ActiveTexture(GLenum texture)
41 {
42     EVENT("(GLenum texture = 0x%X)", texture);
43 
44     Context *context = GetValidGlobalContext();
45     if (context)
46     {
47         if (!context->skipValidation() && !ValidateActiveTexture(context, texture))
48         {
49             return;
50         }
51 
52         context->activeTexture(texture);
53     }
54 }
55 
AttachShader(GLuint program,GLuint shader)56 void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
57 {
58     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
59 
60     Context *context = GetValidGlobalContext();
61     if (context)
62     {
63         if (!context->skipValidation() && !ValidateAttachShader(context, program, shader))
64         {
65             return;
66         }
67 
68         context->attachShader(program, shader);
69     }
70 }
71 
BindAttribLocation(GLuint program,GLuint index,const GLchar * name)72 void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
73 {
74     EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
75 
76     Context *context = GetValidGlobalContext();
77     if (context)
78     {
79         if (!context->skipValidation() &&
80             !ValidateBindAttribLocation(context, program, index, name))
81         {
82             return;
83         }
84 
85         context->bindAttribLocation(program, index, name);
86     }
87 }
88 
BindBuffer(GLenum target,GLuint buffer)89 void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
90 {
91     EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
92 
93     Context *context = GetValidGlobalContext();
94     if (context)
95     {
96         if (!context->skipValidation() && !ValidateBindBuffer(context, target, buffer))
97         {
98             return;
99         }
100 
101         context->bindBuffer(target, buffer);
102     }
103 }
104 
BindFramebuffer(GLenum target,GLuint framebuffer)105 void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
106 {
107     EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
108 
109     Context *context = GetValidGlobalContext();
110     if (context)
111     {
112         if (!context->skipValidation() && !ValidateBindFramebuffer(context, target, framebuffer))
113         {
114             return;
115         }
116 
117         context->bindFramebuffer(target, framebuffer);
118     }
119 }
120 
BindRenderbuffer(GLenum target,GLuint renderbuffer)121 void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
122 {
123     EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
124 
125     Context *context = GetValidGlobalContext();
126     if (context)
127     {
128         if (!context->skipValidation() && !ValidateBindRenderbuffer(context, target, renderbuffer))
129         {
130             return;
131         }
132 
133         context->bindRenderbuffer(target, renderbuffer);
134     }
135 }
136 
BindTexture(GLenum target,GLuint texture)137 void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
138 {
139     EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
140 
141     Context *context = GetValidGlobalContext();
142     if (context)
143     {
144         if (!context->skipValidation() && !ValidateBindTexture(context, target, texture))
145         {
146             return;
147         }
148 
149         context->bindTexture(target, texture);
150     }
151 }
152 
BlendColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)153 void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
154 {
155     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
156           red, green, blue, alpha);
157 
158     Context *context = GetValidGlobalContext();
159     if (context)
160     {
161         context->blendColor(red, green, blue, alpha);
162     }
163 }
164 
BlendEquation(GLenum mode)165 void GL_APIENTRY BlendEquation(GLenum mode)
166 {
167     EVENT("(GLenum mode = 0x%X)", mode);
168 
169     Context *context = GetValidGlobalContext();
170     if (context)
171     {
172         if (!context->skipValidation() && !ValidateBlendEquation(context, mode))
173         {
174             return;
175         }
176 
177         context->blendEquation(mode);
178     }
179 }
180 
BlendEquationSeparate(GLenum modeRGB,GLenum modeAlpha)181 void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
182 {
183     EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
184 
185     Context *context = GetValidGlobalContext();
186     if (context)
187     {
188         if (!context->skipValidation() &&
189             !ValidateBlendEquationSeparate(context, modeRGB, modeAlpha))
190         {
191             return;
192         }
193 
194         context->blendEquationSeparate(modeRGB, modeAlpha);
195     }
196 }
197 
BlendFunc(GLenum sfactor,GLenum dfactor)198 void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
199 {
200     EVENT("(GLenum sfactor = 0x%X, GLenum dfactor = 0x%X)", sfactor, dfactor);
201 
202     Context *context = GetValidGlobalContext();
203     if (context)
204     {
205         if (!context->skipValidation() && !ValidateBlendFunc(context, sfactor, dfactor))
206         {
207             return;
208         }
209 
210         context->blendFunc(sfactor, dfactor);
211     }
212 }
213 
BlendFuncSeparate(GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)214 void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
215 {
216     EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
217           srcRGB, dstRGB, srcAlpha, dstAlpha);
218 
219     Context *context = GetValidGlobalContext();
220     if (context)
221     {
222         if (!context->skipValidation() &&
223             !ValidateBlendFuncSeparate(context, srcRGB, dstRGB, srcAlpha, dstAlpha))
224         {
225             return;
226         }
227 
228         context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
229     }
230 }
231 
BufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)232 void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
233 {
234     EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
235           target, size, data, usage);
236 
237     Context *context = GetValidGlobalContext();
238     if (context)
239     {
240         if (!context->skipValidation() && !ValidateBufferData(context, target, size, data, usage))
241         {
242             return;
243         }
244 
245         context->bufferData(target, size, data, usage);
246     }
247 }
248 
BufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)249 void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
250 {
251     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
252           target, offset, size, data);
253 
254     Context *context = GetValidGlobalContext();
255     if (context)
256     {
257         if (!context->skipValidation() &&
258             !ValidateBufferSubData(context, target, offset, size, data))
259         {
260             return;
261         }
262 
263         context->bufferSubData(target, offset, size, data);
264     }
265 }
266 
CheckFramebufferStatus(GLenum target)267 GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
268 {
269     EVENT("(GLenum target = 0x%X)", target);
270 
271     Context *context = GetValidGlobalContext();
272     if (context)
273     {
274         if (!ValidFramebufferTarget(target))
275         {
276             context->handleError(Error(GL_INVALID_ENUM));
277             return 0;
278         }
279 
280         Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
281         ASSERT(framebuffer);
282 
283         return framebuffer->checkStatus(context->getContextState());
284     }
285 
286     return 0;
287 }
288 
Clear(GLbitfield mask)289 void GL_APIENTRY Clear(GLbitfield mask)
290 {
291     EVENT("(GLbitfield mask = 0x%X)", mask);
292 
293     Context *context = GetValidGlobalContext();
294     if (context)
295     {
296         if (!context->skipValidation() && !ValidateClear(context, mask))
297         {
298             return;
299         }
300 
301         context->clear(mask);
302     }
303 }
304 
ClearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)305 void GL_APIENTRY ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
306 {
307     EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
308           red, green, blue, alpha);
309 
310     Context *context = GetValidGlobalContext();
311     if (context)
312     {
313         context->clearColor(red, green, blue, alpha);
314     }
315 }
316 
ClearDepthf(GLclampf depth)317 void GL_APIENTRY ClearDepthf(GLclampf depth)
318 {
319     EVENT("(GLclampf depth = %f)", depth);
320 
321     Context *context = GetValidGlobalContext();
322     if (context)
323     {
324         context->clearDepthf(depth);
325     }
326 }
327 
ClearStencil(GLint s)328 void GL_APIENTRY ClearStencil(GLint s)
329 {
330     EVENT("(GLint s = %d)", s);
331 
332     Context *context = GetValidGlobalContext();
333     if (context)
334     {
335         context->clearStencil(s);
336     }
337 }
338 
ColorMask(GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)339 void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
340 {
341     EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
342           red, green, blue, alpha);
343 
344     Context *context = GetValidGlobalContext();
345     if (context)
346     {
347         context->colorMask(red, green, blue, alpha);
348     }
349 }
350 
CompileShader(GLuint shader)351 void GL_APIENTRY CompileShader(GLuint shader)
352 {
353     EVENT("(GLuint shader = %d)", shader);
354 
355     Context *context = GetValidGlobalContext();
356     if (context)
357     {
358         Shader *shaderObject = GetValidShader(context, shader);
359         if (!shaderObject)
360         {
361             return;
362         }
363         shaderObject->compile(context);
364     }
365 }
366 
CompressedTexImage2D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)367 void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
368                                       GLint border, GLsizei imageSize, const GLvoid* data)
369 {
370     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
371           "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
372           target, level, internalformat, width, height, border, imageSize, data);
373 
374     Context *context = GetValidGlobalContext();
375     if (context)
376     {
377         if (!context->skipValidation() &&
378             !ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
379                                           border, imageSize, data))
380         {
381             return;
382         }
383 
384         context->compressedTexImage2D(target, level, internalformat, width, height, border,
385                                       imageSize, data);
386     }
387 }
388 
CompressedTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)389 void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
390                                          GLenum format, GLsizei imageSize, const GLvoid* data)
391 {
392     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
393           "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
394           "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
395           target, level, xoffset, yoffset, width, height, format, imageSize, data);
396 
397     Context *context = GetValidGlobalContext();
398     if (context)
399     {
400         if (!context->skipValidation() &&
401             !ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width,
402                                              height, format, imageSize, data))
403         {
404             return;
405         }
406 
407         context->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
408                                          imageSize, data);
409     }
410 }
411 
CopyTexImage2D(GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)412 void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
413 {
414     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
415           "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
416           target, level, internalformat, x, y, width, height, border);
417 
418     Context *context = GetValidGlobalContext();
419     if (context)
420     {
421         if (!context->skipValidation() &&
422             !ValidateCopyTexImage2D(context, target, level, internalformat, x, y, width, height,
423                                     border))
424         {
425             return;
426         }
427         context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
428     }
429 }
430 
CopyTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)431 void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
432 {
433     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
434           "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
435           target, level, xoffset, yoffset, x, y, width, height);
436 
437     Context *context = GetValidGlobalContext();
438     if (context)
439     {
440         if (!context->skipValidation() &&
441             !ValidateCopyTexSubImage2D(context, target, level, xoffset, yoffset, x, y, width,
442                                        height))
443         {
444             return;
445         }
446 
447         context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
448     }
449 }
450 
CreateProgram(void)451 GLuint GL_APIENTRY CreateProgram(void)
452 {
453     EVENT("()");
454 
455     Context *context = GetValidGlobalContext();
456     if (context)
457     {
458         return context->createProgram();
459     }
460 
461     return 0;
462 }
463 
CreateShader(GLenum type)464 GLuint GL_APIENTRY CreateShader(GLenum type)
465 {
466     EVENT("(GLenum type = 0x%X)", type);
467 
468     Context *context = GetValidGlobalContext();
469     if (context)
470     {
471 
472         if (!context->skipValidation() && !ValidateCreateShader(context, type))
473         {
474             return 0;
475         }
476         return context->createShader(type);
477     }
478     return 0;
479 }
480 
CullFace(GLenum mode)481 void GL_APIENTRY CullFace(GLenum mode)
482 {
483     EVENT("(GLenum mode = 0x%X)", mode);
484 
485     Context *context = GetValidGlobalContext();
486     if (context)
487     {
488         switch (mode)
489         {
490           case GL_FRONT:
491           case GL_BACK:
492           case GL_FRONT_AND_BACK:
493             break;
494 
495           default:
496               context->handleError(Error(GL_INVALID_ENUM));
497             return;
498         }
499 
500         context->cullFace(mode);
501     }
502 }
503 
DeleteBuffers(GLsizei n,const GLuint * buffers)504 void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers)
505 {
506     EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
507 
508     Context *context = GetValidGlobalContext();
509     if (context)
510     {
511         if (!context->skipValidation() && !ValidateDeleteBuffers(context, n, buffers))
512         {
513             return;
514         }
515 
516         for (int i = 0; i < n; i++)
517         {
518             context->deleteBuffer(buffers[i]);
519         }
520     }
521 }
522 
DeleteFramebuffers(GLsizei n,const GLuint * framebuffers)523 void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
524 {
525     EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
526 
527     Context *context = GetValidGlobalContext();
528     if (context)
529     {
530         if (!context->skipValidation() && !ValidateDeleteFramebuffers(context, n, framebuffers))
531         {
532             return;
533         }
534 
535         for (int i = 0; i < n; i++)
536         {
537             if (framebuffers[i] != 0)
538             {
539                 context->deleteFramebuffer(framebuffers[i]);
540             }
541         }
542     }
543 }
544 
DeleteProgram(GLuint program)545 void GL_APIENTRY DeleteProgram(GLuint program)
546 {
547     EVENT("(GLuint program = %d)", program);
548 
549     Context *context = GetValidGlobalContext();
550     if (context)
551     {
552         if (program == 0)
553         {
554             return;
555         }
556 
557         if (!context->getProgram(program))
558         {
559             if(context->getShader(program))
560             {
561                 context->handleError(Error(GL_INVALID_OPERATION));
562                 return;
563             }
564             else
565             {
566                 context->handleError(Error(GL_INVALID_VALUE));
567                 return;
568             }
569         }
570 
571         context->deleteProgram(program);
572     }
573 }
574 
DeleteRenderbuffers(GLsizei n,const GLuint * renderbuffers)575 void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
576 {
577     EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
578 
579     Context *context = GetValidGlobalContext();
580     if (context)
581     {
582         if (!context->skipValidation() && !ValidateDeleteRenderbuffers(context, n, renderbuffers))
583         {
584             return;
585         }
586 
587         for (int i = 0; i < n; i++)
588         {
589             context->deleteRenderbuffer(renderbuffers[i]);
590         }
591     }
592 }
593 
DeleteShader(GLuint shader)594 void GL_APIENTRY DeleteShader(GLuint shader)
595 {
596     EVENT("(GLuint shader = %d)", shader);
597 
598     Context *context = GetValidGlobalContext();
599     if (context)
600     {
601         if (shader == 0)
602         {
603             return;
604         }
605 
606         if (!context->getShader(shader))
607         {
608             if(context->getProgram(shader))
609             {
610                 context->handleError(Error(GL_INVALID_OPERATION));
611                 return;
612             }
613             else
614             {
615                 context->handleError(Error(GL_INVALID_VALUE));
616                 return;
617             }
618         }
619 
620         context->deleteShader(shader);
621     }
622 }
623 
DeleteTextures(GLsizei n,const GLuint * textures)624 void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures)
625 {
626     EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
627 
628     Context *context = GetValidGlobalContext();
629     if (context)
630     {
631         if (!context->skipValidation() && !ValidateDeleteTextures(context, n, textures))
632         {
633             return;
634         }
635 
636         for (int i = 0; i < n; i++)
637         {
638             if (textures[i] != 0)
639             {
640                 context->deleteTexture(textures[i]);
641             }
642         }
643     }
644 }
645 
DepthFunc(GLenum func)646 void GL_APIENTRY DepthFunc(GLenum func)
647 {
648     EVENT("(GLenum func = 0x%X)", func);
649 
650     Context *context = GetValidGlobalContext();
651     if (context)
652     {
653         switch (func)
654         {
655           case GL_NEVER:
656           case GL_ALWAYS:
657           case GL_LESS:
658           case GL_LEQUAL:
659           case GL_EQUAL:
660           case GL_GREATER:
661           case GL_GEQUAL:
662           case GL_NOTEQUAL:
663               break;
664 
665           default:
666               context->handleError(Error(GL_INVALID_ENUM));
667             return;
668         }
669 
670         context->depthFunc(func);
671     }
672 }
673 
DepthMask(GLboolean flag)674 void GL_APIENTRY DepthMask(GLboolean flag)
675 {
676     EVENT("(GLboolean flag = %u)", flag);
677 
678     Context *context = GetValidGlobalContext();
679     if (context)
680     {
681         context->depthMask(flag);
682     }
683 }
684 
DepthRangef(GLclampf zNear,GLclampf zFar)685 void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar)
686 {
687     EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
688 
689     Context *context = GetValidGlobalContext();
690     if (context)
691     {
692         context->depthRangef(zNear, zFar);
693     }
694 }
695 
DetachShader(GLuint program,GLuint shader)696 void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
697 {
698     EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
699 
700     Context *context = GetValidGlobalContext();
701     if (context)
702     {
703         Program *programObject = GetValidProgram(context, program);
704         if (!programObject)
705         {
706             return;
707         }
708 
709         Shader *shaderObject = GetValidShader(context, shader);
710         if (!shaderObject)
711         {
712             return;
713         }
714 
715         if (!programObject->detachShader(shaderObject))
716         {
717             context->handleError(Error(GL_INVALID_OPERATION));
718             return;
719         }
720     }
721 }
722 
Disable(GLenum cap)723 void GL_APIENTRY Disable(GLenum cap)
724 {
725     EVENT("(GLenum cap = 0x%X)", cap);
726 
727     Context *context = GetValidGlobalContext();
728     if (context)
729     {
730         if (!context->skipValidation() && !ValidateDisable(context, cap))
731         {
732             return;
733         }
734 
735         context->disable(cap);
736     }
737 }
738 
DisableVertexAttribArray(GLuint index)739 void GL_APIENTRY DisableVertexAttribArray(GLuint index)
740 {
741     EVENT("(GLuint index = %d)", index);
742 
743     Context *context = GetValidGlobalContext();
744     if (context)
745     {
746         if (index >= MAX_VERTEX_ATTRIBS)
747         {
748             context->handleError(Error(GL_INVALID_VALUE));
749             return;
750         }
751 
752         context->disableVertexAttribArray(index);
753     }
754 }
755 
DrawArrays(GLenum mode,GLint first,GLsizei count)756 void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
757 {
758     EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
759 
760     Context *context = GetValidGlobalContext();
761     if (context)
762     {
763         if (!ValidateDrawArrays(context, mode, first, count, 1))
764         {
765             return;
766         }
767 
768         Error error = context->drawArrays(mode, first, count);
769         if (error.isError())
770         {
771             context->handleError(error);
772             return;
773         }
774     }
775 }
776 
DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)777 void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
778 {
779     EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
780           mode, count, type, indices);
781 
782     Context *context = GetValidGlobalContext();
783     if (context)
784     {
785         IndexRange indexRange;
786         if (!ValidateDrawElements(context, mode, count, type, indices, 1, &indexRange))
787         {
788             return;
789         }
790 
791         Error error = context->drawElements(mode, count, type, indices, indexRange);
792         if (error.isError())
793         {
794             context->handleError(error);
795             return;
796         }
797     }
798 }
799 
Enable(GLenum cap)800 void GL_APIENTRY Enable(GLenum cap)
801 {
802     EVENT("(GLenum cap = 0x%X)", cap);
803 
804     Context *context = GetValidGlobalContext();
805     if (context)
806     {
807         if (!context->skipValidation() && !ValidateEnable(context, cap))
808         {
809             return;
810         }
811 
812         context->enable(cap);
813     }
814 }
815 
EnableVertexAttribArray(GLuint index)816 void GL_APIENTRY EnableVertexAttribArray(GLuint index)
817 {
818     EVENT("(GLuint index = %d)", index);
819 
820     Context *context = GetValidGlobalContext();
821     if (context)
822     {
823         if (index >= MAX_VERTEX_ATTRIBS)
824         {
825             context->handleError(Error(GL_INVALID_VALUE));
826             return;
827         }
828 
829         context->enableVertexAttribArray(index);
830     }
831 }
832 
Finish(void)833 void GL_APIENTRY Finish(void)
834 {
835     EVENT("()");
836 
837     Context *context = GetValidGlobalContext();
838     if (context)
839     {
840         Error error = context->finish();
841         if (error.isError())
842         {
843             context->handleError(error);
844             return;
845         }
846     }
847 }
848 
Flush(void)849 void GL_APIENTRY Flush(void)
850 {
851     EVENT("()");
852 
853     Context *context = GetValidGlobalContext();
854     if (context)
855     {
856         Error error = context->flush();
857         if (error.isError())
858         {
859             context->handleError(error);
860             return;
861         }
862     }
863 }
864 
FramebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)865 void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
866 {
867     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
868           "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
869 
870     Context *context = GetValidGlobalContext();
871     if (context)
872     {
873         if (!context->skipValidation() &&
874             !ValidateFramebufferRenderbuffer(context, target, attachment, renderbuffertarget,
875                                              renderbuffer))
876         {
877             return;
878         }
879 
880         context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
881     }
882 }
883 
FramebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)884 void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
885 {
886     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
887           "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
888 
889     Context *context = GetValidGlobalContext();
890     if (context)
891     {
892         if (!context->skipValidation() &&
893             !ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
894         {
895             return;
896         }
897 
898         context->framebufferTexture2D(target, attachment, textarget, texture, level);
899     }
900 }
901 
FrontFace(GLenum mode)902 void GL_APIENTRY FrontFace(GLenum mode)
903 {
904     EVENT("(GLenum mode = 0x%X)", mode);
905 
906     Context *context = GetValidGlobalContext();
907     if (context)
908     {
909         switch (mode)
910         {
911           case GL_CW:
912           case GL_CCW:
913               break;
914           default:
915               context->handleError(Error(GL_INVALID_ENUM));
916             return;
917         }
918 
919         context->frontFace(mode);
920     }
921 }
922 
GenBuffers(GLsizei n,GLuint * buffers)923 void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers)
924 {
925     EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
926 
927     Context *context = GetValidGlobalContext();
928     if (context)
929     {
930         if (!context->skipValidation() && !ValidateGenBuffers(context, n, buffers))
931         {
932             return;
933         }
934 
935         for (int i = 0; i < n; i++)
936         {
937             buffers[i] = context->createBuffer();
938         }
939     }
940 }
941 
GenerateMipmap(GLenum target)942 void GL_APIENTRY GenerateMipmap(GLenum target)
943 {
944     EVENT("(GLenum target = 0x%X)", target);
945 
946     Context *context = GetValidGlobalContext();
947     if (context)
948     {
949         if (!context->skipValidation() && !ValidateGenerateMipmap(context, target))
950         {
951             return;
952         }
953 
954         context->generateMipmap(target);
955     }
956 }
957 
GenFramebuffers(GLsizei n,GLuint * framebuffers)958 void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers)
959 {
960     EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
961 
962     Context *context = GetValidGlobalContext();
963     if (context)
964     {
965         if (!context->skipValidation() && !ValidateGenFramebuffers(context, n, framebuffers))
966         {
967             return;
968         }
969 
970         for (int i = 0; i < n; i++)
971         {
972             framebuffers[i] = context->createFramebuffer();
973         }
974     }
975 }
976 
GenRenderbuffers(GLsizei n,GLuint * renderbuffers)977 void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
978 {
979     EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
980 
981     Context *context = GetValidGlobalContext();
982     if (context)
983     {
984         if (!context->skipValidation() && !ValidateGenRenderbuffers(context, n, renderbuffers))
985         {
986             return;
987         }
988 
989         for (int i = 0; i < n; i++)
990         {
991             renderbuffers[i] = context->createRenderbuffer();
992         }
993     }
994 }
995 
GenTextures(GLsizei n,GLuint * textures)996 void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures)
997 {
998     EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
999 
1000     Context *context = GetValidGlobalContext();
1001     if (context)
1002     {
1003         if (!context->skipValidation() && !ValidateGenTextures(context, n, textures))
1004         {
1005             return;
1006         }
1007 
1008         for (int i = 0; i < n; i++)
1009         {
1010             textures[i] = context->createTexture();
1011         }
1012     }
1013 }
1014 
GetActiveAttrib(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name)1015 void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
1016 {
1017     EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
1018           "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
1019           program, index, bufsize, length, size, type, name);
1020 
1021     Context *context = GetValidGlobalContext();
1022     if (context)
1023     {
1024         if (bufsize < 0)
1025         {
1026             context->handleError(Error(GL_INVALID_VALUE));
1027             return;
1028         }
1029 
1030         Program *programObject = GetValidProgram(context, program);
1031 
1032         if (!programObject)
1033         {
1034             return;
1035         }
1036 
1037         if (index >= (GLuint)programObject->getActiveAttributeCount())
1038         {
1039             context->handleError(Error(GL_INVALID_VALUE));
1040             return;
1041         }
1042 
1043         programObject->getActiveAttribute(index, bufsize, length, size, type, name);
1044     }
1045 }
1046 
GetActiveUniform(GLuint program,GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name)1047 void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
1048 {
1049     EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
1050           "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
1051           program, index, bufsize, length, size, type, name);
1052 
1053 
1054     Context *context = GetValidGlobalContext();
1055     if (context)
1056     {
1057         if (bufsize < 0)
1058         {
1059             context->handleError(Error(GL_INVALID_VALUE));
1060             return;
1061         }
1062 
1063         Program *programObject = GetValidProgram(context, program);
1064 
1065         if (!programObject)
1066         {
1067             return;
1068         }
1069 
1070         if (index >= (GLuint)programObject->getActiveUniformCount())
1071         {
1072             context->handleError(Error(GL_INVALID_VALUE));
1073             return;
1074         }
1075 
1076         programObject->getActiveUniform(index, bufsize, length, size, type, name);
1077     }
1078 }
1079 
GetAttachedShaders(GLuint program,GLsizei maxcount,GLsizei * count,GLuint * shaders)1080 void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
1081 {
1082     EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
1083           program, maxcount, count, shaders);
1084 
1085     Context *context = GetValidGlobalContext();
1086     if (context)
1087     {
1088         if (maxcount < 0)
1089         {
1090             context->handleError(Error(GL_INVALID_VALUE));
1091             return;
1092         }
1093 
1094         Program *programObject = GetValidProgram(context, program);
1095 
1096         if (!programObject)
1097         {
1098             return;
1099         }
1100 
1101         return programObject->getAttachedShaders(maxcount, count, shaders);
1102     }
1103 }
1104 
GetAttribLocation(GLuint program,const GLchar * name)1105 GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name)
1106 {
1107     EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
1108 
1109     Context *context = GetValidGlobalContext();
1110     if (context)
1111     {
1112         Program *programObject = GetValidProgram(context, program);
1113 
1114         if (!programObject)
1115         {
1116             return -1;
1117         }
1118 
1119         if (!programObject->isLinked())
1120         {
1121             context->handleError(Error(GL_INVALID_OPERATION));
1122             return -1;
1123         }
1124 
1125         return programObject->getAttributeLocation(name);
1126     }
1127 
1128     return -1;
1129 }
1130 
GetBooleanv(GLenum pname,GLboolean * params)1131 void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params)
1132 {
1133     EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)",  pname, params);
1134 
1135     Context *context = GetValidGlobalContext();
1136     if (context)
1137     {
1138         GLenum nativeType;
1139         unsigned int numParams = 0;
1140         if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
1141         {
1142             return;
1143         }
1144 
1145         if (nativeType == GL_BOOL)
1146         {
1147             context->getBooleanv(pname, params);
1148         }
1149         else
1150         {
1151             CastStateValues(context, nativeType, pname, numParams, params);
1152         }
1153     }
1154 }
1155 
GetBufferParameteriv(GLenum target,GLenum pname,GLint * params)1156 void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
1157 {
1158     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
1159 
1160     Context *context = GetValidGlobalContext();
1161     if (context)
1162     {
1163         if (!context->skipValidation() &&
1164             !ValidateGetBufferParameteriv(context, target, pname, params))
1165         {
1166             return;
1167         }
1168 
1169         Buffer *buffer = context->getGLState().getTargetBuffer(target);
1170         QueryBufferParameteriv(buffer, pname, params);
1171     }
1172 }
1173 
GetError(void)1174 GLenum GL_APIENTRY GetError(void)
1175 {
1176     EVENT("()");
1177 
1178     Context *context = GetGlobalContext();
1179 
1180     if (context)
1181     {
1182         return context->getError();
1183     }
1184 
1185     return GL_NO_ERROR;
1186 }
1187 
GetFloatv(GLenum pname,GLfloat * params)1188 void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params)
1189 {
1190     EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
1191 
1192     Context *context = GetValidGlobalContext();
1193     if (context)
1194     {
1195         GLenum nativeType;
1196         unsigned int numParams = 0;
1197         if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
1198         {
1199             return;
1200         }
1201 
1202         if (nativeType == GL_FLOAT)
1203         {
1204             context->getFloatv(pname, params);
1205         }
1206         else
1207         {
1208             CastStateValues(context, nativeType, pname, numParams, params);
1209         }
1210     }
1211 }
1212 
GetFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLint * params)1213 void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
1214 {
1215     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
1216           target, attachment, pname, params);
1217 
1218     Context *context = GetValidGlobalContext();
1219     if (context)
1220     {
1221         GLsizei numParams = 0;
1222         if (!context->skipValidation() &&
1223             !ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname,
1224                                                          &numParams))
1225         {
1226             return;
1227         }
1228 
1229         const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1230         QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params);
1231     }
1232 }
1233 
GetIntegerv(GLenum pname,GLint * params)1234 void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params)
1235 {
1236     EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
1237 
1238     Context *context = GetValidGlobalContext();
1239     if (context)
1240     {
1241         GLenum nativeType;
1242         unsigned int numParams = 0;
1243 
1244         if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
1245         {
1246             return;
1247         }
1248 
1249         if (nativeType == GL_INT)
1250         {
1251             context->getIntegerv(pname, params);
1252         }
1253         else
1254         {
1255             CastStateValues(context, nativeType, pname, numParams, params);
1256         }
1257     }
1258 }
1259 
GetProgramiv(GLuint program,GLenum pname,GLint * params)1260 void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
1261 {
1262     EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
1263 
1264     Context *context = GetValidGlobalContext();
1265     if (context)
1266     {
1267         GLsizei numParams = 0;
1268         if (!context->skipValidation() &&
1269             !ValidateGetProgramiv(context, program, pname, &numParams))
1270         {
1271             return;
1272         }
1273 
1274         Program *programObject = context->getProgram(program);
1275         QueryProgramiv(programObject, pname, params);
1276     }
1277 }
1278 
GetProgramInfoLog(GLuint program,GLsizei bufsize,GLsizei * length,GLchar * infolog)1279 void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
1280 {
1281     EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
1282           program, bufsize, length, infolog);
1283 
1284     Context *context = GetValidGlobalContext();
1285     if (context)
1286     {
1287         if (bufsize < 0)
1288         {
1289             context->handleError(Error(GL_INVALID_VALUE));
1290             return;
1291         }
1292 
1293         Program *programObject = GetValidProgram(context, program);
1294         if (!programObject)
1295         {
1296             return;
1297         }
1298 
1299         programObject->getInfoLog(bufsize, length, infolog);
1300     }
1301 }
1302 
GetRenderbufferParameteriv(GLenum target,GLenum pname,GLint * params)1303 void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
1304 {
1305     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
1306 
1307     Context *context = GetValidGlobalContext();
1308     if (context)
1309     {
1310         if (!context->skipValidation() &&
1311             !ValidateGetRenderbufferParameteriv(context, target, pname, params))
1312         {
1313             return;
1314         }
1315 
1316         Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
1317         QueryRenderbufferiv(renderbuffer, pname, params);
1318     }
1319 }
1320 
GetShaderiv(GLuint shader,GLenum pname,GLint * params)1321 void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params)
1322 {
1323     EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
1324 
1325     Context *context = GetValidGlobalContext();
1326     if (context)
1327     {
1328         if (!context->skipValidation() && !ValidateGetShaderiv(context, shader, pname, params))
1329         {
1330             return;
1331         }
1332 
1333         Shader *shaderObject = context->getShader(shader);
1334         QueryShaderiv(shaderObject, pname, params);
1335     }
1336 }
1337 
GetShaderInfoLog(GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * infolog)1338 void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
1339 {
1340     EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
1341           shader, bufsize, length, infolog);
1342 
1343     Context *context = GetValidGlobalContext();
1344     if (context)
1345     {
1346         if (bufsize < 0)
1347         {
1348             context->handleError(Error(GL_INVALID_VALUE));
1349             return;
1350         }
1351 
1352         Shader *shaderObject = GetValidShader(context, shader);
1353         if (!shaderObject)
1354         {
1355             return;
1356         }
1357 
1358         shaderObject->getInfoLog(bufsize, length, infolog);
1359     }
1360 }
1361 
GetShaderPrecisionFormat(GLenum shadertype,GLenum precisiontype,GLint * range,GLint * precision)1362 void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
1363 {
1364     EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
1365           shadertype, precisiontype, range, precision);
1366 
1367     Context *context = GetValidGlobalContext();
1368     if (context)
1369     {
1370         switch (shadertype)
1371         {
1372           case GL_VERTEX_SHADER:
1373             switch (precisiontype)
1374             {
1375               case GL_LOW_FLOAT:
1376                 context->getCaps().vertexLowpFloat.get(range, precision);
1377                 break;
1378               case GL_MEDIUM_FLOAT:
1379                 context->getCaps().vertexMediumpFloat.get(range, precision);
1380                 break;
1381               case GL_HIGH_FLOAT:
1382                 context->getCaps().vertexHighpFloat.get(range, precision);
1383                 break;
1384 
1385               case GL_LOW_INT:
1386                 context->getCaps().vertexLowpInt.get(range, precision);
1387                 break;
1388               case GL_MEDIUM_INT:
1389                 context->getCaps().vertexMediumpInt.get(range, precision);
1390                 break;
1391               case GL_HIGH_INT:
1392                 context->getCaps().vertexHighpInt.get(range, precision);
1393                 break;
1394 
1395               default:
1396                   context->handleError(Error(GL_INVALID_ENUM));
1397                 return;
1398             }
1399             break;
1400           case GL_FRAGMENT_SHADER:
1401             switch (precisiontype)
1402             {
1403               case GL_LOW_FLOAT:
1404                 context->getCaps().fragmentLowpFloat.get(range, precision);
1405                 break;
1406               case GL_MEDIUM_FLOAT:
1407                 context->getCaps().fragmentMediumpFloat.get(range, precision);
1408                 break;
1409               case GL_HIGH_FLOAT:
1410                 context->getCaps().fragmentHighpFloat.get(range, precision);
1411                 break;
1412 
1413               case GL_LOW_INT:
1414                 context->getCaps().fragmentLowpInt.get(range, precision);
1415                 break;
1416               case GL_MEDIUM_INT:
1417                 context->getCaps().fragmentMediumpInt.get(range, precision);
1418                 break;
1419               case GL_HIGH_INT:
1420                 context->getCaps().fragmentHighpInt.get(range, precision);
1421                 break;
1422 
1423               default:
1424                   context->handleError(Error(GL_INVALID_ENUM));
1425                 return;
1426             }
1427             break;
1428           default:
1429               context->handleError(Error(GL_INVALID_ENUM));
1430             return;
1431         }
1432 
1433     }
1434 }
1435 
GetShaderSource(GLuint shader,GLsizei bufsize,GLsizei * length,GLchar * source)1436 void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
1437 {
1438     EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
1439           shader, bufsize, length, source);
1440 
1441     Context *context = GetValidGlobalContext();
1442     if (context)
1443     {
1444         if (bufsize < 0)
1445         {
1446             context->handleError(Error(GL_INVALID_VALUE));
1447             return;
1448         }
1449 
1450         Shader *shaderObject = GetValidShader(context, shader);
1451         if (!shaderObject)
1452         {
1453             return;
1454         }
1455 
1456         shaderObject->getSource(bufsize, length, source);
1457     }
1458 }
1459 
GetString(GLenum name)1460 const GLubyte *GL_APIENTRY GetString(GLenum name)
1461 {
1462     EVENT("(GLenum name = 0x%X)", name);
1463 
1464     Context *context = GetValidGlobalContext();
1465 
1466     if (context)
1467     {
1468         switch (name)
1469         {
1470             case GL_VENDOR:
1471                 return reinterpret_cast<const GLubyte *>("Google Inc.");
1472 
1473             case GL_RENDERER:
1474                 return reinterpret_cast<const GLubyte *>(context->getRendererString());
1475 
1476             case GL_VERSION:
1477                 if (context->getClientMajorVersion() == 2)
1478                 {
1479                     return reinterpret_cast<const GLubyte *>(
1480                         "OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")");
1481                 }
1482                 else
1483                 {
1484                     return reinterpret_cast<const GLubyte *>(
1485                         "OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")");
1486                 }
1487 
1488             case GL_SHADING_LANGUAGE_VERSION:
1489                 if (context->getClientMajorVersion() == 2)
1490                 {
1491                     return reinterpret_cast<const GLubyte *>(
1492                         "OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")");
1493                 }
1494                 else
1495                 {
1496                     return reinterpret_cast<const GLubyte *>(
1497                         "OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")");
1498                 }
1499 
1500             case GL_EXTENSIONS:
1501                 return reinterpret_cast<const GLubyte *>(context->getExtensionString());
1502 
1503             default:
1504                 context->handleError(Error(GL_INVALID_ENUM));
1505             return nullptr;
1506         }
1507     }
1508 
1509     return nullptr;
1510 }
1511 
GetTexParameterfv(GLenum target,GLenum pname,GLfloat * params)1512 void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
1513 {
1514     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
1515 
1516     Context *context = GetValidGlobalContext();
1517     if (context)
1518     {
1519         if (!context->skipValidation() &&
1520             !ValidateGetTexParameterfv(context, target, pname, params))
1521         {
1522             return;
1523         }
1524 
1525         Texture *texture = context->getTargetTexture(target);
1526         QueryTexParameterfv(texture, pname, params);
1527     }
1528 }
1529 
GetTexParameteriv(GLenum target,GLenum pname,GLint * params)1530 void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
1531 {
1532     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
1533 
1534     Context *context = GetValidGlobalContext();
1535     if (context)
1536     {
1537         if (!context->skipValidation() &&
1538             !ValidateGetTexParameteriv(context, target, pname, params))
1539         {
1540             return;
1541         }
1542 
1543         Texture *texture = context->getTargetTexture(target);
1544         QueryTexParameteriv(texture, pname, params);
1545     }
1546 }
1547 
GetUniformfv(GLuint program,GLint location,GLfloat * params)1548 void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params)
1549 {
1550     EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
1551 
1552     Context *context = GetValidGlobalContext();
1553     if (context)
1554     {
1555         if (!ValidateGetUniformfv(context, program, location, params))
1556         {
1557             return;
1558         }
1559 
1560         Program *programObject = context->getProgram(program);
1561         ASSERT(programObject);
1562 
1563         programObject->getUniformfv(location, params);
1564     }
1565 }
1566 
GetUniformiv(GLuint program,GLint location,GLint * params)1567 void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params)
1568 {
1569     EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
1570 
1571     Context *context = GetValidGlobalContext();
1572     if (context)
1573     {
1574         if (!ValidateGetUniformiv(context, program, location, params))
1575         {
1576             return;
1577         }
1578 
1579         Program *programObject = context->getProgram(program);
1580         ASSERT(programObject);
1581 
1582         programObject->getUniformiv(location, params);
1583     }
1584 }
1585 
GetUniformLocation(GLuint program,const GLchar * name)1586 GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name)
1587 {
1588     EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
1589 
1590     Context *context = GetValidGlobalContext();
1591     if (context)
1592     {
1593         if (strstr(name, "gl_") == name)
1594         {
1595             return -1;
1596         }
1597 
1598         Program *programObject = GetValidProgram(context, program);
1599 
1600         if (!programObject)
1601         {
1602             return -1;
1603         }
1604 
1605         if (!programObject->isLinked())
1606         {
1607             context->handleError(Error(GL_INVALID_OPERATION));
1608             return -1;
1609         }
1610 
1611         return programObject->getUniformLocation(name);
1612     }
1613 
1614     return -1;
1615 }
1616 
GetVertexAttribfv(GLuint index,GLenum pname,GLfloat * params)1617 void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
1618 {
1619     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
1620 
1621     Context *context = GetValidGlobalContext();
1622     if (context)
1623     {
1624         if (!context->skipValidation() && !ValidateGetVertexAttribfv(context, index, pname, params))
1625         {
1626             return;
1627         }
1628 
1629         const VertexAttribCurrentValueData &currentValues =
1630             context->getGLState().getVertexAttribCurrentValue(index);
1631         const VertexAttribute &attrib =
1632             context->getGLState().getVertexArray()->getVertexAttribute(index);
1633         QueryVertexAttribfv(attrib, currentValues, pname, params);
1634     }
1635 }
1636 
GetVertexAttribiv(GLuint index,GLenum pname,GLint * params)1637 void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
1638 {
1639     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
1640 
1641     Context *context = GetValidGlobalContext();
1642     if (context)
1643     {
1644         if (!context->skipValidation() && !ValidateGetVertexAttribiv(context, index, pname, params))
1645         {
1646             return;
1647         }
1648 
1649         const VertexAttribCurrentValueData &currentValues =
1650             context->getGLState().getVertexAttribCurrentValue(index);
1651         const VertexAttribute &attrib =
1652             context->getGLState().getVertexArray()->getVertexAttribute(index);
1653         QueryVertexAttribiv(attrib, currentValues, pname, params);
1654     }
1655 }
1656 
GetVertexAttribPointerv(GLuint index,GLenum pname,GLvoid ** pointer)1657 void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
1658 {
1659     EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
1660 
1661     Context *context = GetValidGlobalContext();
1662     if (context)
1663     {
1664         if (!context->skipValidation() &&
1665             !ValidateGetVertexAttribPointerv(context, index, pname, pointer))
1666         {
1667             return;
1668         }
1669 
1670         const VertexAttribute &attrib =
1671             context->getGLState().getVertexArray()->getVertexAttribute(index);
1672         QueryVertexAttribPointerv(attrib, pname, pointer);
1673     }
1674 }
1675 
Hint(GLenum target,GLenum mode)1676 void GL_APIENTRY Hint(GLenum target, GLenum mode)
1677 {
1678     EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
1679 
1680     Context *context = GetValidGlobalContext();
1681     if (context)
1682     {
1683         switch (mode)
1684         {
1685           case GL_FASTEST:
1686           case GL_NICEST:
1687           case GL_DONT_CARE:
1688             break;
1689 
1690           default:
1691               context->handleError(Error(GL_INVALID_ENUM));
1692             return;
1693         }
1694 
1695         switch (target)
1696         {
1697           case GL_GENERATE_MIPMAP_HINT:
1698           case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
1699               break;
1700 
1701           default:
1702               context->handleError(Error(GL_INVALID_ENUM));
1703             return;
1704         }
1705 
1706         context->hint(target, mode);
1707     }
1708 }
1709 
IsBuffer(GLuint buffer)1710 GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
1711 {
1712     EVENT("(GLuint buffer = %d)", buffer);
1713 
1714     Context *context = GetValidGlobalContext();
1715     if (context && buffer)
1716     {
1717         Buffer *bufferObject = context->getBuffer(buffer);
1718 
1719         if (bufferObject)
1720         {
1721             return GL_TRUE;
1722         }
1723     }
1724 
1725     return GL_FALSE;
1726 }
1727 
IsEnabled(GLenum cap)1728 GLboolean GL_APIENTRY IsEnabled(GLenum cap)
1729 {
1730     EVENT("(GLenum cap = 0x%X)", cap);
1731 
1732     Context *context = GetValidGlobalContext();
1733     if (context)
1734     {
1735         if (!context->skipValidation() && !ValidateIsEnabled(context, cap))
1736         {
1737             return GL_FALSE;
1738         }
1739 
1740         return context->getGLState().getEnableFeature(cap);
1741     }
1742 
1743     return false;
1744 }
1745 
IsFramebuffer(GLuint framebuffer)1746 GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
1747 {
1748     EVENT("(GLuint framebuffer = %d)", framebuffer);
1749 
1750     Context *context = GetValidGlobalContext();
1751     if (context && framebuffer)
1752     {
1753         Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
1754 
1755         if (framebufferObject)
1756         {
1757             return GL_TRUE;
1758         }
1759     }
1760 
1761     return GL_FALSE;
1762 }
1763 
IsProgram(GLuint program)1764 GLboolean GL_APIENTRY IsProgram(GLuint program)
1765 {
1766     EVENT("(GLuint program = %d)", program);
1767 
1768     Context *context = GetValidGlobalContext();
1769     if (context && program)
1770     {
1771         Program *programObject = context->getProgram(program);
1772 
1773         if (programObject)
1774         {
1775             return GL_TRUE;
1776         }
1777     }
1778 
1779     return GL_FALSE;
1780 }
1781 
IsRenderbuffer(GLuint renderbuffer)1782 GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
1783 {
1784     EVENT("(GLuint renderbuffer = %d)", renderbuffer);
1785 
1786     Context *context = GetValidGlobalContext();
1787     if (context && renderbuffer)
1788     {
1789         Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
1790 
1791         if (renderbufferObject)
1792         {
1793             return GL_TRUE;
1794         }
1795     }
1796 
1797     return GL_FALSE;
1798 }
1799 
IsShader(GLuint shader)1800 GLboolean GL_APIENTRY IsShader(GLuint shader)
1801 {
1802     EVENT("(GLuint shader = %d)", shader);
1803 
1804     Context *context = GetValidGlobalContext();
1805     if (context && shader)
1806     {
1807         Shader *shaderObject = context->getShader(shader);
1808 
1809         if (shaderObject)
1810         {
1811             return GL_TRUE;
1812         }
1813     }
1814 
1815     return GL_FALSE;
1816 }
1817 
IsTexture(GLuint texture)1818 GLboolean GL_APIENTRY IsTexture(GLuint texture)
1819 {
1820     EVENT("(GLuint texture = %d)", texture);
1821 
1822     Context *context = GetValidGlobalContext();
1823     if (context && texture)
1824     {
1825         Texture *textureObject = context->getTexture(texture);
1826 
1827         if (textureObject)
1828         {
1829             return GL_TRUE;
1830         }
1831     }
1832 
1833     return GL_FALSE;
1834 }
1835 
LineWidth(GLfloat width)1836 void GL_APIENTRY LineWidth(GLfloat width)
1837 {
1838     EVENT("(GLfloat width = %f)", width);
1839 
1840     Context *context = GetValidGlobalContext();
1841     if (context)
1842     {
1843         if (width <= 0.0f)
1844         {
1845             context->handleError(Error(GL_INVALID_VALUE));
1846             return;
1847         }
1848 
1849         context->lineWidth(width);
1850     }
1851 }
1852 
LinkProgram(GLuint program)1853 void GL_APIENTRY LinkProgram(GLuint program)
1854 {
1855     EVENT("(GLuint program = %d)", program);
1856 
1857     Context *context = GetValidGlobalContext();
1858     if (context)
1859     {
1860         if (!context->skipValidation() && !ValidateLinkProgram(context, program))
1861         {
1862             return;
1863         }
1864 
1865         Program *programObject = GetValidProgram(context, program);
1866         if (!programObject)
1867         {
1868             return;
1869         }
1870 
1871         Error error = programObject->link(context->getContextState());
1872         if (error.isError())
1873         {
1874             context->handleError(error);
1875             return;
1876         }
1877     }
1878 }
1879 
PixelStorei(GLenum pname,GLint param)1880 void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
1881 {
1882     EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
1883 
1884     Context *context = GetValidGlobalContext();
1885     if (context)
1886     {
1887         if (context->getClientMajorVersion() < 3)
1888         {
1889             switch (pname)
1890             {
1891               case GL_UNPACK_IMAGE_HEIGHT:
1892               case GL_UNPACK_SKIP_IMAGES:
1893                   context->handleError(Error(GL_INVALID_ENUM));
1894                   return;
1895 
1896               case GL_UNPACK_ROW_LENGTH:
1897               case GL_UNPACK_SKIP_ROWS:
1898               case GL_UNPACK_SKIP_PIXELS:
1899                   if (!context->getExtensions().unpackSubimage)
1900                   {
1901                       context->handleError(Error(GL_INVALID_ENUM));
1902                       return;
1903                   }
1904                   break;
1905 
1906               case GL_PACK_ROW_LENGTH:
1907               case GL_PACK_SKIP_ROWS:
1908               case GL_PACK_SKIP_PIXELS:
1909                   if (!context->getExtensions().packSubimage)
1910                   {
1911                       context->handleError(Error(GL_INVALID_ENUM));
1912                       return;
1913                   }
1914                   break;
1915             }
1916         }
1917 
1918         if (param < 0)
1919         {
1920             context->handleError(
1921                 Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
1922             return;
1923         }
1924 
1925         switch (pname)
1926         {
1927           case GL_UNPACK_ALIGNMENT:
1928             if (param != 1 && param != 2 && param != 4 && param != 8)
1929             {
1930                 context->handleError(Error(GL_INVALID_VALUE));
1931                 return;
1932             }
1933             break;
1934 
1935           case GL_PACK_ALIGNMENT:
1936             if (param != 1 && param != 2 && param != 4 && param != 8)
1937             {
1938                 context->handleError(Error(GL_INVALID_VALUE));
1939                 return;
1940             }
1941             break;
1942 
1943           case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
1944           case GL_UNPACK_ROW_LENGTH:
1945           case GL_UNPACK_IMAGE_HEIGHT:
1946           case GL_UNPACK_SKIP_IMAGES:
1947           case GL_UNPACK_SKIP_ROWS:
1948           case GL_UNPACK_SKIP_PIXELS:
1949           case GL_PACK_ROW_LENGTH:
1950           case GL_PACK_SKIP_ROWS:
1951           case GL_PACK_SKIP_PIXELS:
1952             break;
1953 
1954           default:
1955               context->handleError(Error(GL_INVALID_ENUM));
1956             return;
1957         }
1958 
1959         context->pixelStorei(pname, param);
1960     }
1961 }
1962 
PolygonOffset(GLfloat factor,GLfloat units)1963 void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
1964 {
1965     EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
1966 
1967     Context *context = GetValidGlobalContext();
1968     if (context)
1969     {
1970         context->polygonOffset(factor, units);
1971     }
1972 }
1973 
ReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1974 void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1975                             GLenum format, GLenum type, GLvoid* pixels)
1976 {
1977     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
1978           "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
1979           x, y, width, height, format, type,  pixels);
1980 
1981     Context *context = GetValidGlobalContext();
1982     if (context)
1983     {
1984         if (!context->skipValidation() &&
1985             !ValidateReadPixels(context, x, y, width, height, format, type, pixels))
1986         {
1987             return;
1988         }
1989 
1990         context->readPixels(x, y, width, height, format, type, pixels);
1991     }
1992 }
1993 
ReleaseShaderCompiler(void)1994 void GL_APIENTRY ReleaseShaderCompiler(void)
1995 {
1996     EVENT("()");
1997 
1998     Context *context = GetValidGlobalContext();
1999 
2000     if (context)
2001     {
2002         Compiler *compiler = context->getCompiler();
2003         Error error = compiler->release();
2004         if (error.isError())
2005         {
2006             context->handleError(error);
2007             return;
2008         }
2009     }
2010 }
2011 
RenderbufferStorage(GLenum target,GLenum internalformat,GLsizei width,GLsizei height)2012 void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
2013 {
2014     EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
2015           target, internalformat, width, height);
2016 
2017     Context *context = GetValidGlobalContext();
2018     if (context)
2019     {
2020         if (!ValidateRenderbufferStorageParametersANGLE(context, target, 0, internalformat,
2021                                                         width, height))
2022         {
2023             return;
2024         }
2025 
2026         Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
2027         Error error = renderbuffer->setStorage(internalformat, width, height);
2028         if (error.isError())
2029         {
2030             context->handleError(error);
2031             return;
2032         }
2033     }
2034 }
2035 
SampleCoverage(GLclampf value,GLboolean invert)2036 void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert)
2037 {
2038     EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
2039 
2040     Context* context = GetValidGlobalContext();
2041 
2042     if (context)
2043     {
2044         context->sampleCoverage(value, invert);
2045     }
2046 }
2047 
Scissor(GLint x,GLint y,GLsizei width,GLsizei height)2048 void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
2049 {
2050     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
2051 
2052     Context* context = GetValidGlobalContext();
2053     if (context)
2054     {
2055         if (width < 0 || height < 0)
2056         {
2057             context->handleError(Error(GL_INVALID_VALUE));
2058             return;
2059         }
2060 
2061         context->scissor(x, y, width, height);
2062     }
2063 }
2064 
ShaderBinary(GLsizei n,const GLuint * shaders,GLenum binaryformat,const GLvoid * binary,GLsizei length)2065 void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
2066 {
2067     EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
2068           "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
2069           n, shaders, binaryformat, binary, length);
2070 
2071     Context* context = GetValidGlobalContext();
2072     if (context)
2073     {
2074         const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
2075         if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end())
2076         {
2077             context->handleError(Error(GL_INVALID_ENUM));
2078             return;
2079         }
2080 
2081         // No binary shader formats are supported.
2082         UNIMPLEMENTED();
2083     }
2084 }
2085 
ShaderSource(GLuint shader,GLsizei count,const GLchar * const * string,const GLint * length)2086 void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
2087 {
2088     EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
2089           shader, count, string, length);
2090 
2091     Context *context = GetValidGlobalContext();
2092     if (context)
2093     {
2094         if (count < 0)
2095         {
2096             context->handleError(Error(GL_INVALID_VALUE));
2097             return;
2098         }
2099 
2100         Shader *shaderObject = GetValidShader(context, shader);
2101         if (!shaderObject)
2102         {
2103             return;
2104         }
2105         shaderObject->setSource(count, string, length);
2106     }
2107 }
2108 
StencilFunc(GLenum func,GLint ref,GLuint mask)2109 void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
2110 {
2111     StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2112 }
2113 
StencilFuncSeparate(GLenum face,GLenum func,GLint ref,GLuint mask)2114 void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
2115 {
2116     EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
2117 
2118     Context *context = GetValidGlobalContext();
2119     if (context)
2120     {
2121         switch (face)
2122         {
2123           case GL_FRONT:
2124           case GL_BACK:
2125           case GL_FRONT_AND_BACK:
2126             break;
2127 
2128           default:
2129               context->handleError(Error(GL_INVALID_ENUM));
2130             return;
2131         }
2132 
2133         switch (func)
2134         {
2135           case GL_NEVER:
2136           case GL_ALWAYS:
2137           case GL_LESS:
2138           case GL_LEQUAL:
2139           case GL_EQUAL:
2140           case GL_GEQUAL:
2141           case GL_GREATER:
2142           case GL_NOTEQUAL:
2143             break;
2144 
2145           default:
2146               context->handleError(Error(GL_INVALID_ENUM));
2147             return;
2148         }
2149 
2150         context->stencilFuncSeparate(face, func, ref, mask);
2151     }
2152 }
2153 
StencilMask(GLuint mask)2154 void GL_APIENTRY StencilMask(GLuint mask)
2155 {
2156     StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
2157 }
2158 
StencilMaskSeparate(GLenum face,GLuint mask)2159 void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
2160 {
2161     EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
2162 
2163     Context *context = GetValidGlobalContext();
2164     if (context)
2165     {
2166         switch (face)
2167         {
2168           case GL_FRONT:
2169           case GL_BACK:
2170           case GL_FRONT_AND_BACK:
2171             break;
2172 
2173           default:
2174               context->handleError(Error(GL_INVALID_ENUM));
2175             return;
2176         }
2177 
2178         context->stencilMaskSeparate(face, mask);
2179     }
2180 }
2181 
StencilOp(GLenum fail,GLenum zfail,GLenum zpass)2182 void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
2183 {
2184     StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
2185 }
2186 
StencilOpSeparate(GLenum face,GLenum fail,GLenum zfail,GLenum zpass)2187 void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
2188 {
2189     EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
2190           face, fail, zfail, zpass);
2191 
2192     Context *context = GetValidGlobalContext();
2193     if (context)
2194     {
2195         switch (face)
2196         {
2197           case GL_FRONT:
2198           case GL_BACK:
2199           case GL_FRONT_AND_BACK:
2200             break;
2201 
2202           default:
2203               context->handleError(Error(GL_INVALID_ENUM));
2204             return;
2205         }
2206 
2207         switch (fail)
2208         {
2209           case GL_ZERO:
2210           case GL_KEEP:
2211           case GL_REPLACE:
2212           case GL_INCR:
2213           case GL_DECR:
2214           case GL_INVERT:
2215           case GL_INCR_WRAP:
2216           case GL_DECR_WRAP:
2217             break;
2218 
2219           default:
2220               context->handleError(Error(GL_INVALID_ENUM));
2221             return;
2222         }
2223 
2224         switch (zfail)
2225         {
2226           case GL_ZERO:
2227           case GL_KEEP:
2228           case GL_REPLACE:
2229           case GL_INCR:
2230           case GL_DECR:
2231           case GL_INVERT:
2232           case GL_INCR_WRAP:
2233           case GL_DECR_WRAP:
2234             break;
2235 
2236           default:
2237               context->handleError(Error(GL_INVALID_ENUM));
2238             return;
2239         }
2240 
2241         switch (zpass)
2242         {
2243           case GL_ZERO:
2244           case GL_KEEP:
2245           case GL_REPLACE:
2246           case GL_INCR:
2247           case GL_DECR:
2248           case GL_INVERT:
2249           case GL_INCR_WRAP:
2250           case GL_DECR_WRAP:
2251             break;
2252 
2253           default:
2254               context->handleError(Error(GL_INVALID_ENUM));
2255             return;
2256         }
2257 
2258         context->stencilOpSeparate(face, fail, zfail, zpass);
2259     }
2260 }
2261 
TexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)2262 void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
2263                             GLint border, GLenum format, GLenum type, const GLvoid* pixels)
2264 {
2265     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
2266           "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
2267           target, level, internalformat, width, height, border, format, type, pixels);
2268 
2269     Context *context = GetValidGlobalContext();
2270     if (context)
2271     {
2272         if (!context->skipValidation() &&
2273             !ValidateTexImage2D(context, target, level, internalformat, width, height, border,
2274                                 format, type, pixels))
2275         {
2276             return;
2277         }
2278 
2279         context->texImage2D(target, level, internalformat, width, height, border, format, type,
2280                             pixels);
2281     }
2282 }
2283 
TexParameterf(GLenum target,GLenum pname,GLfloat param)2284 void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
2285 {
2286     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
2287 
2288     Context *context = GetValidGlobalContext();
2289     if (context)
2290     {
2291         if (!context->skipValidation() && !ValidateTexParameterf(context, target, pname, param))
2292         {
2293             return;
2294         }
2295 
2296         Texture *texture = context->getTargetTexture(target);
2297         SetTexParameterf(texture, pname, param);
2298     }
2299 }
2300 
TexParameterfv(GLenum target,GLenum pname,const GLfloat * params)2301 void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
2302 {
2303     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat* params = 0x%0.8p)", target,
2304           pname, params);
2305 
2306     Context *context = GetValidGlobalContext();
2307     if (context)
2308     {
2309         if (!context->skipValidation() && !ValidateTexParameterfv(context, target, pname, params))
2310         {
2311             return;
2312         }
2313 
2314         Texture *texture = context->getTargetTexture(target);
2315         SetTexParameterfv(texture, pname, params);
2316     }
2317 }
2318 
TexParameteri(GLenum target,GLenum pname,GLint param)2319 void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
2320 {
2321     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
2322 
2323     Context *context = GetValidGlobalContext();
2324     if (context)
2325     {
2326         if (!context->skipValidation() && !ValidateTexParameteri(context, target, pname, param))
2327         {
2328             return;
2329         }
2330 
2331         Texture *texture = context->getTargetTexture(target);
2332         SetTexParameteri(texture, pname, param);
2333     }
2334 }
2335 
TexParameteriv(GLenum target,GLenum pname,const GLint * params)2336 void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params)
2337 {
2338     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLint* params = 0x%0.8p)", target,
2339           pname, params);
2340 
2341     Context *context = GetValidGlobalContext();
2342     if (context)
2343     {
2344         if (!context->skipValidation() && !ValidateTexParameteriv(context, target, pname, params))
2345         {
2346             return;
2347         }
2348 
2349         Texture *texture = context->getTargetTexture(target);
2350         SetTexParameteriv(texture, pname, params);
2351     }
2352 }
2353 
TexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)2354 void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
2355                                GLenum format, GLenum type, const GLvoid* pixels)
2356 {
2357     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
2358           "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
2359           "const GLvoid* pixels = 0x%0.8p)",
2360            target, level, xoffset, yoffset, width, height, format, type, pixels);
2361 
2362     Context *context = GetValidGlobalContext();
2363     if (context)
2364     {
2365         if (!context->skipValidation() &&
2366             !ValidateTexSubImage2D(context, target, level, xoffset, yoffset, width, height, format,
2367                                    type, pixels))
2368         {
2369             return;
2370         }
2371 
2372         context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
2373                                pixels);
2374     }
2375 }
2376 
Uniform1f(GLint location,GLfloat x)2377 void GL_APIENTRY Uniform1f(GLint location, GLfloat x)
2378 {
2379     Uniform1fv(location, 1, &x);
2380 }
2381 
Uniform1fv(GLint location,GLsizei count,const GLfloat * v)2382 void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
2383 {
2384     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
2385 
2386     Context *context = GetValidGlobalContext();
2387     if (context)
2388     {
2389         if (!ValidateUniform(context, GL_FLOAT, location, count))
2390         {
2391             return;
2392         }
2393 
2394         Program *program = context->getGLState().getProgram();
2395         program->setUniform1fv(location, count, v);
2396     }
2397 }
2398 
Uniform1i(GLint location,GLint x)2399 void GL_APIENTRY Uniform1i(GLint location, GLint x)
2400 {
2401     Uniform1iv(location, 1, &x);
2402 }
2403 
Uniform1iv(GLint location,GLsizei count,const GLint * v)2404 void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v)
2405 {
2406     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
2407 
2408     Context *context = GetValidGlobalContext();
2409     if (context)
2410     {
2411         if (!ValidateUniform(context, GL_INT, location, count))
2412         {
2413             return;
2414         }
2415 
2416         Program *program = context->getGLState().getProgram();
2417         program->setUniform1iv(location, count, v);
2418     }
2419 }
2420 
Uniform2f(GLint location,GLfloat x,GLfloat y)2421 void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y)
2422 {
2423     GLfloat xy[2] = {x, y};
2424 
2425     Uniform2fv(location, 1, xy);
2426 }
2427 
Uniform2fv(GLint location,GLsizei count,const GLfloat * v)2428 void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
2429 {
2430     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
2431 
2432     Context *context = GetValidGlobalContext();
2433     if (context)
2434     {
2435         if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
2436         {
2437             return;
2438         }
2439 
2440         Program *program = context->getGLState().getProgram();
2441         program->setUniform2fv(location, count, v);
2442     }
2443 }
2444 
Uniform2i(GLint location,GLint x,GLint y)2445 void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y)
2446 {
2447     GLint xy[2] = {x, y};
2448 
2449     Uniform2iv(location, 1, xy);
2450 }
2451 
Uniform2iv(GLint location,GLsizei count,const GLint * v)2452 void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v)
2453 {
2454     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
2455 
2456     Context *context = GetValidGlobalContext();
2457     if (context)
2458     {
2459         if (!ValidateUniform(context, GL_INT_VEC2, location, count))
2460         {
2461             return;
2462         }
2463 
2464         Program *program = context->getGLState().getProgram();
2465         program->setUniform2iv(location, count, v);
2466     }
2467 }
2468 
Uniform3f(GLint location,GLfloat x,GLfloat y,GLfloat z)2469 void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
2470 {
2471     GLfloat xyz[3] = {x, y, z};
2472 
2473     Uniform3fv(location, 1, xyz);
2474 }
2475 
Uniform3fv(GLint location,GLsizei count,const GLfloat * v)2476 void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
2477 {
2478     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
2479 
2480     Context *context = GetValidGlobalContext();
2481     if (context)
2482     {
2483         if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
2484         {
2485             return;
2486         }
2487 
2488         Program *program = context->getGLState().getProgram();
2489         program->setUniform3fv(location, count, v);
2490     }
2491 }
2492 
Uniform3i(GLint location,GLint x,GLint y,GLint z)2493 void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z)
2494 {
2495     GLint xyz[3] = {x, y, z};
2496 
2497     Uniform3iv(location, 1, xyz);
2498 }
2499 
Uniform3iv(GLint location,GLsizei count,const GLint * v)2500 void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v)
2501 {
2502     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
2503 
2504     Context *context = GetValidGlobalContext();
2505     if (context)
2506     {
2507         if (!ValidateUniform(context, GL_INT_VEC3, location, count))
2508         {
2509             return;
2510         }
2511 
2512         Program *program = context->getGLState().getProgram();
2513         program->setUniform3iv(location, count, v);
2514     }
2515 }
2516 
Uniform4f(GLint location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)2517 void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2518 {
2519     GLfloat xyzw[4] = {x, y, z, w};
2520 
2521     Uniform4fv(location, 1, xyzw);
2522 }
2523 
Uniform4fv(GLint location,GLsizei count,const GLfloat * v)2524 void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
2525 {
2526     EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
2527 
2528     Context *context = GetValidGlobalContext();
2529     if (context)
2530     {
2531         if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
2532         {
2533             return;
2534         }
2535 
2536         Program *program = context->getGLState().getProgram();
2537         program->setUniform4fv(location, count, v);
2538     }
2539 }
2540 
Uniform4i(GLint location,GLint x,GLint y,GLint z,GLint w)2541 void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
2542 {
2543     GLint xyzw[4] = {x, y, z, w};
2544 
2545     Uniform4iv(location, 1, xyzw);
2546 }
2547 
Uniform4iv(GLint location,GLsizei count,const GLint * v)2548 void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v)
2549 {
2550     EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
2551 
2552     Context *context = GetValidGlobalContext();
2553     if (context)
2554     {
2555         if (!ValidateUniform(context, GL_INT_VEC4, location, count))
2556         {
2557             return;
2558         }
2559 
2560         Program *program = context->getGLState().getProgram();
2561         program->setUniform4iv(location, count, v);
2562     }
2563 }
2564 
UniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2565 void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2566 {
2567     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
2568           location, count, transpose, value);
2569 
2570     Context *context = GetValidGlobalContext();
2571     if (context)
2572     {
2573         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
2574         {
2575             return;
2576         }
2577 
2578         Program *program = context->getGLState().getProgram();
2579         program->setUniformMatrix2fv(location, count, transpose, value);
2580     }
2581 }
2582 
UniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2583 void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2584 {
2585     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
2586           location, count, transpose, value);
2587 
2588     Context *context = GetValidGlobalContext();
2589     if (context)
2590     {
2591         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
2592         {
2593             return;
2594         }
2595 
2596         Program *program = context->getGLState().getProgram();
2597         program->setUniformMatrix3fv(location, count, transpose, value);
2598     }
2599 }
2600 
UniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2601 void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
2602 {
2603     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
2604           location, count, transpose, value);
2605 
2606     Context *context = GetValidGlobalContext();
2607     if (context)
2608     {
2609         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
2610         {
2611             return;
2612         }
2613 
2614         Program *program = context->getGLState().getProgram();
2615         program->setUniformMatrix4fv(location, count, transpose, value);
2616     }
2617 }
2618 
UseProgram(GLuint program)2619 void GL_APIENTRY UseProgram(GLuint program)
2620 {
2621     EVENT("(GLuint program = %d)", program);
2622 
2623     Context *context = GetValidGlobalContext();
2624     if (context)
2625     {
2626         if (!context->skipValidation() && !ValidateUseProgram(context, program))
2627         {
2628             return;
2629         }
2630 
2631         context->useProgram(program);
2632     }
2633 }
2634 
ValidateProgram(GLuint program)2635 void GL_APIENTRY ValidateProgram(GLuint program)
2636 {
2637     EVENT("(GLuint program = %d)", program);
2638 
2639     Context *context = GetValidGlobalContext();
2640     if (context)
2641     {
2642         Program *programObject = GetValidProgram(context, program);
2643 
2644         if (!programObject)
2645         {
2646             return;
2647         }
2648 
2649         programObject->validate(context->getCaps());
2650     }
2651 }
2652 
VertexAttrib1f(GLuint index,GLfloat x)2653 void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
2654 {
2655     EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
2656 
2657     Context *context = GetValidGlobalContext();
2658     if (context)
2659     {
2660         if (index >= MAX_VERTEX_ATTRIBS)
2661         {
2662             context->handleError(Error(GL_INVALID_VALUE));
2663             return;
2664         }
2665 
2666         context->vertexAttrib1f(index, x);
2667     }
2668 }
2669 
VertexAttrib1fv(GLuint index,const GLfloat * values)2670 void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values)
2671 {
2672     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
2673 
2674     Context *context = GetValidGlobalContext();
2675     if (context)
2676     {
2677         if (index >= MAX_VERTEX_ATTRIBS)
2678         {
2679             context->handleError(Error(GL_INVALID_VALUE));
2680             return;
2681         }
2682 
2683         context->vertexAttrib1fv(index, values);
2684     }
2685 }
2686 
VertexAttrib2f(GLuint index,GLfloat x,GLfloat y)2687 void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
2688 {
2689     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
2690 
2691     Context *context = GetValidGlobalContext();
2692     if (context)
2693     {
2694         if (index >= MAX_VERTEX_ATTRIBS)
2695         {
2696             context->handleError(Error(GL_INVALID_VALUE));
2697             return;
2698         }
2699 
2700         context->vertexAttrib2f(index, x, y);
2701     }
2702 }
2703 
VertexAttrib2fv(GLuint index,const GLfloat * values)2704 void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values)
2705 {
2706     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
2707 
2708     Context *context = GetValidGlobalContext();
2709     if (context)
2710     {
2711         if (index >= MAX_VERTEX_ATTRIBS)
2712         {
2713             context->handleError(Error(GL_INVALID_VALUE));
2714             return;
2715         }
2716 
2717         context->vertexAttrib2fv(index, values);
2718     }
2719 }
2720 
VertexAttrib3f(GLuint index,GLfloat x,GLfloat y,GLfloat z)2721 void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
2722 {
2723     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
2724 
2725     Context *context = GetValidGlobalContext();
2726     if (context)
2727     {
2728         if (index >= MAX_VERTEX_ATTRIBS)
2729         {
2730             context->handleError(Error(GL_INVALID_VALUE));
2731             return;
2732         }
2733 
2734         context->vertexAttrib3f(index, x, y, z);
2735     }
2736 }
2737 
VertexAttrib3fv(GLuint index,const GLfloat * values)2738 void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values)
2739 {
2740     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
2741 
2742     Context *context = GetValidGlobalContext();
2743     if (context)
2744     {
2745         if (index >= MAX_VERTEX_ATTRIBS)
2746         {
2747             context->handleError(Error(GL_INVALID_VALUE));
2748             return;
2749         }
2750 
2751         context->vertexAttrib3fv(index, values);
2752     }
2753 }
2754 
VertexAttrib4f(GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)2755 void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
2756 {
2757     EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
2758 
2759     Context *context = GetValidGlobalContext();
2760     if (context)
2761     {
2762         if (index >= MAX_VERTEX_ATTRIBS)
2763         {
2764             context->handleError(Error(GL_INVALID_VALUE));
2765             return;
2766         }
2767 
2768         context->vertexAttrib4f(index, x, y, z, w);
2769     }
2770 }
2771 
VertexAttrib4fv(GLuint index,const GLfloat * values)2772 void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values)
2773 {
2774     EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
2775 
2776     Context *context = GetValidGlobalContext();
2777     if (context)
2778     {
2779         if (index >= MAX_VERTEX_ATTRIBS)
2780         {
2781             context->handleError(Error(GL_INVALID_VALUE));
2782             return;
2783         }
2784 
2785         context->vertexAttrib4fv(index, values);
2786     }
2787 }
2788 
VertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * ptr)2789 void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
2790 {
2791     EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
2792           "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
2793           index, size, type, normalized, stride, ptr);
2794 
2795     Context *context = GetValidGlobalContext();
2796     if (context)
2797     {
2798         if (index >= MAX_VERTEX_ATTRIBS)
2799         {
2800             context->handleError(Error(GL_INVALID_VALUE));
2801             return;
2802         }
2803 
2804         if (size < 1 || size > 4)
2805         {
2806             context->handleError(Error(GL_INVALID_VALUE));
2807             return;
2808         }
2809 
2810         switch (type)
2811         {
2812             case GL_BYTE:
2813             case GL_UNSIGNED_BYTE:
2814             case GL_SHORT:
2815             case GL_UNSIGNED_SHORT:
2816             case GL_FIXED:
2817             case GL_FLOAT:
2818                 break;
2819 
2820             case GL_HALF_FLOAT:
2821             case GL_INT:
2822             case GL_UNSIGNED_INT:
2823             case GL_INT_2_10_10_10_REV:
2824             case GL_UNSIGNED_INT_2_10_10_10_REV:
2825                 if (context->getClientMajorVersion() < 3)
2826                 {
2827                     context->handleError(Error(GL_INVALID_ENUM));
2828                     return;
2829                 }
2830                 break;
2831 
2832             default:
2833                 context->handleError(Error(GL_INVALID_ENUM));
2834                 return;
2835         }
2836 
2837         if (stride < 0)
2838         {
2839             context->handleError(Error(GL_INVALID_VALUE));
2840             return;
2841         }
2842 
2843         if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
2844         {
2845             context->handleError(Error(GL_INVALID_OPERATION));
2846             return;
2847         }
2848 
2849         // [OpenGL ES 3.0.2] Section 2.8 page 24:
2850         // An INVALID_OPERATION error is generated when a non-zero vertex array object
2851         // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2852         // and the pointer argument is not NULL.
2853         if (context->getGLState().getVertexArray()->id() != 0 &&
2854             context->getGLState().getArrayBufferId() == 0 && ptr != NULL)
2855         {
2856             context->handleError(Error(GL_INVALID_OPERATION));
2857             return;
2858         }
2859 
2860         context->vertexAttribPointer(index, size, type, normalized, stride, ptr);
2861     }
2862 }
2863 
Viewport(GLint x,GLint y,GLsizei width,GLsizei height)2864 void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
2865 {
2866     EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
2867 
2868     Context *context = GetValidGlobalContext();
2869     if (context)
2870     {
2871         if (width < 0 || height < 0)
2872         {
2873             context->handleError(Error(GL_INVALID_VALUE));
2874             return;
2875         }
2876 
2877         context->viewport(x, y, width, height);
2878     }
2879 }
2880 
2881 }  // namespace gl
2882