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_3_0.cpp : Implements the GLES 3.0 entry points.
8 
9 #include "libGLESv2/entry_points_gles_3_0.h"
10 #include "libGLESv2/entry_points_gles_2_0_ext.h"
11 #include "libGLESv2/global_state.h"
12 
13 #include "libANGLE/formatutils.h"
14 #include "libANGLE/Buffer.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Error.h"
17 #include "libANGLE/Fence.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/Query.h"
20 #include "libANGLE/VertexArray.h"
21 
22 #include "libANGLE/validationES.h"
23 #include "libANGLE/validationES3.h"
24 #include "libANGLE/queryconversions.h"
25 #include "libANGLE/queryutils.h"
26 
27 #include "common/debug.h"
28 
29 namespace gl
30 {
31 
ReadBuffer(GLenum mode)32 void GL_APIENTRY ReadBuffer(GLenum mode)
33 {
34     EVENT("(GLenum mode = 0x%X)", mode);
35 
36     Context *context = GetValidGlobalContext();
37     if (context)
38     {
39         if (!context->skipValidation() && !ValidateReadBuffer(context, mode))
40         {
41             return;
42         }
43 
44         context->readBuffer(mode);
45     }
46 }
47 
DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)48 void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
49 {
50     EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
51           "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
52 
53     Context *context = GetValidGlobalContext();
54     if (context)
55     {
56         IndexRange indexRange;
57         if (!context->skipValidation() &&
58             !ValidateDrawRangeElements(context, mode, start, end, count, type, indices,
59                                        &indexRange))
60         {
61             return;
62         }
63 
64         // As long as index validation is done, it doesn't matter whether the context receives a drawElements or
65         // a drawRangeElements call - the GL back-end is free to choose to call drawRangeElements based on the
66         // validated index range. If index validation is removed, adding drawRangeElements to the context interface
67         // should be reconsidered.
68         Error error =
69             context->drawRangeElements(mode, start, end, count, type, indices, indexRange);
70         if (error.isError())
71         {
72             context->handleError(error);
73             return;
74         }
75     }
76 }
77 
TexImage3D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const GLvoid * pixels)78 void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
79 {
80     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
81           "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
82           "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
83           target, level, internalformat, width, height, depth, border, format, type, pixels);
84 
85     Context *context = GetValidGlobalContext();
86     if (context)
87     {
88         if (!context->skipValidation() &&
89             !ValidateTexImage3D(context, target, level, internalformat, width, height, depth,
90                                 border, format, type, pixels))
91         {
92             return;
93         }
94 
95         context->texImage3D(target, level, internalformat, width, height, depth, border, format,
96                             type, pixels);
97     }
98 }
99 
TexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels)100 void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
101 {
102     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
103           "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
104           "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
105           target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
106 
107     Context *context = GetValidGlobalContext();
108     if (context)
109     {
110         if (!context->skipValidation() &&
111             !ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
112                                    depth, format, type, pixels))
113         {
114             return;
115         }
116 
117         context->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
118                                format, type, pixels);
119     }
120 }
121 
CopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)122 void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
123 {
124     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
125           "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
126           target, level, xoffset, yoffset, zoffset, x, y, width, height);
127 
128     Context *context = GetValidGlobalContext();
129     if (context)
130     {
131         if (!context->skipValidation() &&
132             !ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y,
133                                        width, height))
134         {
135             return;
136         }
137 
138         context->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
139     }
140 }
141 
CompressedTexImage3D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const GLvoid * data)142 void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
143 {
144     EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
145           "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
146           "const GLvoid* data = 0x%0.8p)",
147           target, level, internalformat, width, height, depth, border, imageSize, data);
148 
149     Context *context = GetValidGlobalContext();
150     if (context)
151     {
152         if (!context->skipValidation() &&
153             !ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
154                                           depth, border, imageSize, data))
155         {
156             return;
157         }
158 
159         context->compressedTexImage3D(target, level, internalformat, width, height, depth, border,
160                                       imageSize, data);
161     }
162 }
163 
CompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)164 void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
165 {
166     EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
167         "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
168         "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
169         target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
170 
171     Context *context = GetValidGlobalContext();
172     if (context)
173     {
174         if (!context->skipValidation() &&
175             !ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset,
176                                              width, height, depth, format, imageSize, data))
177         {
178             return;
179         }
180 
181         context->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
182                                          depth, format, imageSize, data);
183     }
184 }
185 
GenQueries(GLsizei n,GLuint * ids)186 void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids)
187 {
188     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
189 
190     Context *context = GetValidGlobalContext();
191     if (context)
192     {
193         if (!context->skipValidation() && !ValidateGenQueries(context, n, ids))
194         {
195             return;
196         }
197 
198         for (GLsizei i = 0; i < n; i++)
199         {
200             ids[i] = context->createQuery();
201         }
202     }
203 }
204 
DeleteQueries(GLsizei n,const GLuint * ids)205 void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids)
206 {
207     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
208 
209     Context *context = GetValidGlobalContext();
210     if (context)
211     {
212         if (!context->skipValidation() && !ValidateDeleteQueries(context, n, ids))
213         {
214             return;
215         }
216 
217         for (int i = 0; i < n; i++)
218         {
219             context->deleteQuery(ids[i]);
220         }
221     }
222 }
223 
IsQuery(GLuint id)224 GLboolean GL_APIENTRY IsQuery(GLuint id)
225 {
226     EVENT("(GLuint id = %u)", id);
227 
228     Context *context = GetValidGlobalContext();
229     if (context)
230     {
231         if (context->getClientMajorVersion() < 3)
232         {
233             context->handleError(Error(GL_INVALID_OPERATION));
234             return GL_FALSE;
235         }
236 
237         return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
238     }
239 
240     return GL_FALSE;
241 }
242 
BeginQuery(GLenum target,GLuint id)243 void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
244 {
245     EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
246 
247     Context *context = GetValidGlobalContext();
248     if (context)
249     {
250         if (!ValidateBeginQuery(context, target, id))
251         {
252             return;
253         }
254 
255         Error error = context->beginQuery(target, id);
256         if (error.isError())
257         {
258             context->handleError(error);
259             return;
260         }
261     }
262 }
263 
EndQuery(GLenum target)264 void GL_APIENTRY EndQuery(GLenum target)
265 {
266     EVENT("(GLenum target = 0x%X)", target);
267 
268     Context *context = GetValidGlobalContext();
269     if (context)
270     {
271         if (!ValidateEndQuery(context, target))
272         {
273             return;
274         }
275 
276         Error error = context->endQuery(target);
277         if (error.isError())
278         {
279             context->handleError(error);
280             return;
281         }
282     }
283 }
284 
GetQueryiv(GLenum target,GLenum pname,GLint * params)285 void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params)
286 {
287     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
288 
289     Context *context = GetValidGlobalContext();
290     if (context)
291     {
292         if (!ValidateGetQueryiv(context, target, pname, params))
293         {
294             return;
295         }
296 
297         context->getQueryiv(target, pname, params);
298     }
299 }
300 
GetQueryObjectuiv(GLuint id,GLenum pname,GLuint * params)301 void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
302 {
303     EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
304 
305     Context *context = GetValidGlobalContext();
306     if (context)
307     {
308         if (!ValidateGetQueryObjectuiv(context, id, pname, params))
309         {
310             return;
311         }
312 
313         context->getQueryObjectuiv(id, pname, params);
314     }
315 }
316 
UnmapBuffer(GLenum target)317 GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
318 {
319     EVENT("(GLenum target = 0x%X)", target);
320 
321     Context *context = GetValidGlobalContext();
322     if (context)
323     {
324         if (!context->skipValidation() && !ValidateUnmapBuffer(context, target))
325         {
326             return GL_FALSE;
327         }
328 
329         return context->unmapBuffer(target);
330     }
331 
332     return GL_FALSE;
333 }
334 
GetBufferPointerv(GLenum target,GLenum pname,GLvoid ** params)335 void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
336 {
337     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
338 
339     Context *context = GetValidGlobalContext();
340     if (context)
341     {
342         if (!context->skipValidation() &&
343             !ValidateGetBufferPointerv(context, target, pname, params))
344         {
345             return;
346         }
347 
348         context->getBufferPointerv(target, pname, params);
349     }
350 }
351 
DrawBuffers(GLsizei n,const GLenum * bufs)352 void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs)
353 {
354     Context *context = GetValidGlobalContext();
355     if (context)
356     {
357         if (!context->skipValidation() && !ValidateDrawBuffers(context, n, bufs))
358         {
359             return;
360         }
361 
362         context->drawBuffers(n, bufs);
363     }
364 }
365 
UniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)366 void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
367 {
368     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
369           location, count, transpose, value);
370 
371     Context *context = GetValidGlobalContext();
372     if (context)
373     {
374         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
375         {
376             return;
377         }
378 
379         Program *program = context->getGLState().getProgram();
380         program->setUniformMatrix2x3fv(location, count, transpose, value);
381     }
382 }
383 
UniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)384 void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
385 {
386     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
387           location, count, transpose, value);
388 
389     Context *context = GetValidGlobalContext();
390     if (context)
391     {
392         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
393         {
394             return;
395         }
396 
397         Program *program = context->getGLState().getProgram();
398         program->setUniformMatrix3x2fv(location, count, transpose, value);
399     }
400 }
401 
UniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)402 void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
403 {
404     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
405           location, count, transpose, value);
406 
407     Context *context = GetValidGlobalContext();
408     if (context)
409     {
410         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
411         {
412             return;
413         }
414 
415         Program *program = context->getGLState().getProgram();
416         program->setUniformMatrix2x4fv(location, count, transpose, value);
417     }
418 }
419 
UniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)420 void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
421 {
422     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
423           location, count, transpose, value);
424 
425     Context *context = GetValidGlobalContext();
426     if (context)
427     {
428         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
429         {
430             return;
431         }
432 
433         Program *program = context->getGLState().getProgram();
434         program->setUniformMatrix4x2fv(location, count, transpose, value);
435     }
436 }
437 
UniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)438 void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
439 {
440     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
441           location, count, transpose, value);
442 
443     Context *context = GetValidGlobalContext();
444     if (context)
445     {
446         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
447         {
448             return;
449         }
450 
451         Program *program = context->getGLState().getProgram();
452         program->setUniformMatrix3x4fv(location, count, transpose, value);
453     }
454 }
455 
UniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)456 void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
457 {
458     EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
459           location, count, transpose, value);
460 
461     Context *context = GetValidGlobalContext();
462     if (context)
463     {
464         if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
465         {
466             return;
467         }
468 
469         Program *program = context->getGLState().getProgram();
470         program->setUniformMatrix4x3fv(location, count, transpose, value);
471     }
472 }
473 
BlitFramebuffer(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)474 void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
475 {
476     EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
477           "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
478           srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
479 
480     Context *context = GetValidGlobalContext();
481     if (context)
482     {
483         if (!context->skipValidation() &&
484             !ValidateBlitFramebuffer(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
485                                      dstY1, mask, filter))
486         {
487             return;
488         }
489 
490         context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
491                                  filter);
492     }
493 }
494 
RenderbufferStorageMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)495 void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
496 {
497     EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
498         target, samples, internalformat, width, height);
499 
500     Context *context = GetValidGlobalContext();
501     if (context)
502     {
503         if (context->getClientMajorVersion() < 3)
504         {
505             context->handleError(Error(GL_INVALID_OPERATION));
506             return;
507         }
508 
509         if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height))
510         {
511             return;
512         }
513 
514         Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
515         renderbuffer->setStorageMultisample(samples, internalformat, width, height);
516     }
517 }
518 
FramebufferTextureLayer(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)519 void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
520 {
521     EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
522         target, attachment, texture, level, layer);
523 
524     Context *context = GetValidGlobalContext();
525     if (context)
526     {
527         if (!context->skipValidation() &&
528             !ValidateFramebufferTextureLayer(context, target, attachment, texture, level, layer))
529         {
530             return;
531         }
532 
533         context->framebufferTextureLayer(target, attachment, texture, level, layer);
534     }
535 }
536 
MapBufferRange(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access)537 GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
538 {
539     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
540           target, offset, length, access);
541 
542     Context *context = GetValidGlobalContext();
543     if (context)
544     {
545         if (!context->skipValidation() &&
546             !ValidateMapBufferRange(context, target, offset, length, access))
547         {
548             return nullptr;
549         }
550 
551         return context->mapBufferRange(target, offset, length, access);
552     }
553 
554     return nullptr;
555 }
556 
FlushMappedBufferRange(GLenum target,GLintptr offset,GLsizeiptr length)557 void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
558 {
559     EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
560 
561     Context *context = GetValidGlobalContext();
562     if (context)
563     {
564         if (!context->skipValidation() &&
565             !ValidateFlushMappedBufferRange(context, target, offset, length))
566         {
567             return;
568         }
569 
570         context->flushMappedBufferRange(target, offset, length);
571     }
572 }
573 
BindVertexArray(GLuint array)574 void GL_APIENTRY BindVertexArray(GLuint array)
575 {
576     EVENT("(GLuint array = %u)", array);
577 
578     Context *context = GetValidGlobalContext();
579     if (context)
580     {
581         if (!ValidateBindVertexArray(context, array))
582         {
583             return;
584         }
585 
586         context->bindVertexArray(array);
587     }
588 }
589 
DeleteVertexArrays(GLsizei n,const GLuint * arrays)590 void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays)
591 {
592     EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
593 
594     Context *context = GetValidGlobalContext();
595     if (context)
596     {
597         if (!context->skipValidation() && !ValidateDeleteVertexArrays(context, n, arrays))
598         {
599             return;
600         }
601 
602         for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
603         {
604             if (arrays[arrayIndex] != 0)
605             {
606                 context->deleteVertexArray(arrays[arrayIndex]);
607             }
608         }
609     }
610 }
611 
GenVertexArrays(GLsizei n,GLuint * arrays)612 void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays)
613 {
614     EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
615 
616     Context *context = GetValidGlobalContext();
617     if (context)
618     {
619         if (!context->skipValidation() && !ValidateGenVertexArrays(context, n, arrays))
620         {
621             return;
622         }
623 
624         for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
625         {
626             arrays[arrayIndex] = context->createVertexArray();
627         }
628     }
629 }
630 
IsVertexArray(GLuint array)631 GLboolean GL_APIENTRY IsVertexArray(GLuint array)
632 {
633     EVENT("(GLuint array = %u)", array);
634 
635     Context *context = GetValidGlobalContext();
636     if (context)
637     {
638         if (!ValidateIsVertexArray(context))
639         {
640             return GL_FALSE;
641         }
642 
643         if (array == 0)
644         {
645             return GL_FALSE;
646         }
647 
648         VertexArray *vao = context->getVertexArray(array);
649 
650         return (vao != NULL ? GL_TRUE : GL_FALSE);
651     }
652 
653     return GL_FALSE;
654 }
655 
GetIntegeri_v(GLenum target,GLuint index,GLint * data)656 void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data)
657 {
658     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
659           target, index, data);
660 
661     Context *context = GetValidGlobalContext();
662     if (context)
663     {
664         if (!context->skipValidation() && !ValidateGetIntegeri_v(context, target, index, data))
665         {
666             return;
667         }
668         context->getIntegeri_v(target, index, data);
669     }
670 }
671 
BeginTransformFeedback(GLenum primitiveMode)672 void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
673 {
674     EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
675 
676     Context *context = GetValidGlobalContext();
677     if (context)
678     {
679         if (!context->skipValidation() && !ValidateBeginTransformFeedback(context, primitiveMode))
680         {
681             return;
682         }
683 
684         context->beginTransformFeedback(primitiveMode);
685     }
686 }
687 
EndTransformFeedback(void)688 void GL_APIENTRY EndTransformFeedback(void)
689 {
690     EVENT("(void)");
691 
692     Context *context = GetValidGlobalContext();
693     if (context)
694     {
695         if (context->getClientMajorVersion() < 3)
696         {
697             context->handleError(Error(GL_INVALID_OPERATION));
698             return;
699         }
700 
701         TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
702         ASSERT(transformFeedback != NULL);
703 
704         if (!transformFeedback->isActive())
705         {
706             context->handleError(Error(GL_INVALID_OPERATION));
707             return;
708         }
709 
710         transformFeedback->end();
711     }
712 }
713 
BindBufferRange(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)714 void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
715 {
716     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
717           target, index, buffer, offset, size);
718 
719     Context *context = GetValidGlobalContext();
720     if (context)
721     {
722         if (context->getClientMajorVersion() < 3)
723         {
724             context->handleError(Error(GL_INVALID_OPERATION));
725             return;
726         }
727 
728         const Caps &caps = context->getCaps();
729         switch (target)
730         {
731           case GL_TRANSFORM_FEEDBACK_BUFFER:
732             if (index >= caps.maxTransformFeedbackSeparateAttributes)
733             {
734                 context->handleError(Error(GL_INVALID_VALUE));
735                 return;
736             }
737             break;
738 
739           case GL_UNIFORM_BUFFER:
740             if (index >= caps.maxUniformBufferBindings)
741             {
742                 context->handleError(Error(GL_INVALID_VALUE));
743                 return;
744             }
745             break;
746 
747           default:
748               context->handleError(Error(GL_INVALID_ENUM));
749             return;
750         }
751 
752         if (buffer != 0 && size <= 0)
753         {
754             context->handleError(Error(GL_INVALID_VALUE));
755             return;
756         }
757 
758         if (!context->getGLState().isBindGeneratesResourceEnabled() &&
759             !context->isBufferGenerated(buffer))
760         {
761             context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
762             return;
763         }
764 
765         switch (target)
766         {
767           case GL_TRANSFORM_FEEDBACK_BUFFER:
768             {
769                 // size and offset must be a multiple of 4
770                 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
771                 {
772                     context->handleError(Error(GL_INVALID_VALUE));
773                     return;
774                 }
775 
776                 // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
777                 TransformFeedback *curTransformFeedback =
778                     context->getGLState().getCurrentTransformFeedback();
779                 if (curTransformFeedback && curTransformFeedback->isActive())
780                 {
781                     context->handleError(Error(GL_INVALID_OPERATION));
782                     return;
783                 }
784 
785                 context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
786                 context->bindGenericTransformFeedbackBuffer(buffer);
787                 break;
788             }
789 
790           case GL_UNIFORM_BUFFER:
791 
792             // it is an error to bind an offset not a multiple of the alignment
793             if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
794             {
795                 context->handleError(Error(GL_INVALID_VALUE));
796                 return;
797             }
798 
799             context->bindIndexedUniformBuffer(buffer, index, offset, size);
800             context->bindGenericUniformBuffer(buffer);
801             break;
802 
803           default:
804             UNREACHABLE();
805         }
806     }
807 }
808 
BindBufferBase(GLenum target,GLuint index,GLuint buffer)809 void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
810 {
811     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
812           target, index, buffer);
813 
814     Context *context = GetValidGlobalContext();
815     if (context)
816     {
817         if (context->getClientMajorVersion() < 3)
818         {
819             context->handleError(Error(GL_INVALID_OPERATION));
820             return;
821         }
822 
823         const Caps &caps = context->getCaps();
824         switch (target)
825         {
826           case GL_TRANSFORM_FEEDBACK_BUFFER:
827             if (index >= caps.maxTransformFeedbackSeparateAttributes)
828             {
829                 context->handleError(Error(GL_INVALID_VALUE));
830                 return;
831             }
832             break;
833 
834           case GL_UNIFORM_BUFFER:
835             if (index >= caps.maxUniformBufferBindings)
836             {
837                 context->handleError(Error(GL_INVALID_VALUE));
838                 return;
839             }
840             break;
841 
842           default:
843               context->handleError(Error(GL_INVALID_ENUM));
844             return;
845         }
846 
847         if (!context->getGLState().isBindGeneratesResourceEnabled() &&
848             !context->isBufferGenerated(buffer))
849         {
850             context->handleError(Error(GL_INVALID_OPERATION, "Buffer was not generated"));
851             return;
852         }
853 
854         switch (target)
855         {
856           case GL_TRANSFORM_FEEDBACK_BUFFER:
857             {
858                 // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
859                 TransformFeedback *curTransformFeedback =
860                     context->getGLState().getCurrentTransformFeedback();
861                 if (curTransformFeedback && curTransformFeedback->isActive())
862                 {
863                     context->handleError(Error(GL_INVALID_OPERATION));
864                     return;
865                 }
866 
867                 context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
868                 context->bindGenericTransformFeedbackBuffer(buffer);
869                 break;
870             }
871           case GL_UNIFORM_BUFFER:
872             context->bindIndexedUniformBuffer(buffer, index, 0, 0);
873             context->bindGenericUniformBuffer(buffer);
874             break;
875 
876           default:
877             UNREACHABLE();
878         }
879     }
880 }
881 
TransformFeedbackVaryings(GLuint program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)882 void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
883 {
884     EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
885           program, count, varyings, bufferMode);
886 
887     Context *context = GetValidGlobalContext();
888     if (context)
889     {
890         if (context->getClientMajorVersion() < 3)
891         {
892             context->handleError(Error(GL_INVALID_OPERATION));
893             return;
894         }
895 
896         if (count < 0)
897         {
898             context->handleError(Error(GL_INVALID_VALUE));
899             return;
900         }
901 
902         const Caps &caps = context->getCaps();
903         switch (bufferMode)
904         {
905           case GL_INTERLEAVED_ATTRIBS:
906             break;
907           case GL_SEPARATE_ATTRIBS:
908             if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
909             {
910                 context->handleError(Error(GL_INVALID_VALUE));
911                 return;
912             }
913             break;
914           default:
915               context->handleError(Error(GL_INVALID_ENUM));
916             return;
917         }
918 
919         Program *programObject = GetValidProgram(context, program);
920         if (!programObject)
921         {
922             return;
923         }
924 
925         programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
926     }
927 }
928 
GetTransformFeedbackVarying(GLuint program,GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name)929 void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
930 {
931     EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
932           "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
933           program, index, bufSize, length, size, type, name);
934 
935     Context *context = GetValidGlobalContext();
936     if (context)
937     {
938         if (context->getClientMajorVersion() < 3)
939         {
940             context->handleError(Error(GL_INVALID_OPERATION));
941             return;
942         }
943 
944         if (bufSize < 0)
945         {
946             context->handleError(Error(GL_INVALID_VALUE));
947             return;
948         }
949 
950         Program *programObject = GetValidProgram(context, program);
951         if (!programObject)
952         {
953             return;
954         }
955 
956         if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
957         {
958             context->handleError(Error(GL_INVALID_VALUE));
959             return;
960         }
961 
962         programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
963     }
964 }
965 
VertexAttribIPointer(GLuint index,GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)966 void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
967 {
968     EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
969           index, size, type, stride, pointer);
970 
971     Context *context = GetValidGlobalContext();
972     if (context)
973     {
974         if (context->getClientMajorVersion() < 3)
975         {
976             context->handleError(Error(GL_INVALID_OPERATION));
977             return;
978         }
979 
980         if (index >= MAX_VERTEX_ATTRIBS)
981         {
982             context->handleError(Error(GL_INVALID_VALUE));
983             return;
984         }
985 
986         if (size < 1 || size > 4)
987         {
988             context->handleError(Error(GL_INVALID_VALUE));
989             return;
990         }
991 
992         switch (type)
993         {
994           case GL_BYTE:
995           case GL_UNSIGNED_BYTE:
996           case GL_SHORT:
997           case GL_UNSIGNED_SHORT:
998           case GL_INT:
999           case GL_UNSIGNED_INT:
1000             break;
1001 
1002           default:
1003               context->handleError(Error(GL_INVALID_ENUM));
1004             return;
1005         }
1006 
1007         if (stride < 0)
1008         {
1009             context->handleError(Error(GL_INVALID_VALUE));
1010             return;
1011         }
1012 
1013         // [OpenGL ES 3.0.2] Section 2.8 page 24:
1014         // An INVALID_OPERATION error is generated when a non-zero vertex array object
1015         // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
1016         // and the pointer argument is not NULL.
1017         if (context->getGLState().getVertexArray()->id() != 0 &&
1018             context->getGLState().getArrayBufferId() == 0 && pointer != NULL)
1019         {
1020             context->handleError(Error(GL_INVALID_OPERATION));
1021             return;
1022         }
1023 
1024         context->vertexAttribIPointer(index, size, type, stride, pointer);
1025     }
1026 }
1027 
GetVertexAttribIiv(GLuint index,GLenum pname,GLint * params)1028 void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
1029 {
1030     EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
1031           index, pname, params);
1032 
1033     Context *context = GetValidGlobalContext();
1034     if (context)
1035     {
1036         if (!context->skipValidation() &&
1037             !ValidateGetVertexAttribIiv(context, index, pname, params))
1038         {
1039             return;
1040         }
1041 
1042         const VertexAttribCurrentValueData &currentValues =
1043             context->getGLState().getVertexAttribCurrentValue(index);
1044         const VertexAttribute &attrib =
1045             context->getGLState().getVertexArray()->getVertexAttribute(index);
1046         QueryVertexAttribIiv(attrib, currentValues, pname, params);
1047     }
1048 }
1049 
GetVertexAttribIuiv(GLuint index,GLenum pname,GLuint * params)1050 void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
1051 {
1052     EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
1053           index, pname, params);
1054 
1055     Context *context = GetValidGlobalContext();
1056     if (context)
1057     {
1058         if (!context->skipValidation() &&
1059             !ValidateGetVertexAttribIuiv(context, index, pname, params))
1060         {
1061             return;
1062         }
1063 
1064         const VertexAttribCurrentValueData &currentValues =
1065             context->getGLState().getVertexAttribCurrentValue(index);
1066         const VertexAttribute &attrib =
1067             context->getGLState().getVertexArray()->getVertexAttribute(index);
1068         QueryVertexAttribIuiv(attrib, currentValues, pname, params);
1069     }
1070 }
1071 
VertexAttribI4i(GLuint index,GLint x,GLint y,GLint z,GLint w)1072 void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
1073 {
1074     EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
1075           index, x, y, z, w);
1076 
1077     Context *context = GetValidGlobalContext();
1078     if (context)
1079     {
1080         if (context->getClientMajorVersion() < 3)
1081         {
1082             context->handleError(Error(GL_INVALID_OPERATION));
1083             return;
1084         }
1085 
1086         if (index >= MAX_VERTEX_ATTRIBS)
1087         {
1088             context->handleError(Error(GL_INVALID_VALUE));
1089             return;
1090         }
1091 
1092         context->vertexAttribI4i(index, x, y, z, w);
1093     }
1094 }
1095 
VertexAttribI4ui(GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)1096 void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
1097 {
1098     EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
1099           index, x, y, z, w);
1100 
1101     Context *context = GetValidGlobalContext();
1102     if (context)
1103     {
1104         if (context->getClientMajorVersion() < 3)
1105         {
1106             context->handleError(Error(GL_INVALID_OPERATION));
1107             return;
1108         }
1109 
1110         if (index >= MAX_VERTEX_ATTRIBS)
1111         {
1112             context->handleError(Error(GL_INVALID_VALUE));
1113             return;
1114         }
1115 
1116         context->vertexAttribI4ui(index, x, y, z, w);
1117     }
1118 }
1119 
VertexAttribI4iv(GLuint index,const GLint * v)1120 void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v)
1121 {
1122     EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
1123 
1124     Context *context = GetValidGlobalContext();
1125     if (context)
1126     {
1127         if (context->getClientMajorVersion() < 3)
1128         {
1129             context->handleError(Error(GL_INVALID_OPERATION));
1130             return;
1131         }
1132 
1133         if (index >= MAX_VERTEX_ATTRIBS)
1134         {
1135             context->handleError(Error(GL_INVALID_VALUE));
1136             return;
1137         }
1138 
1139         context->vertexAttribI4iv(index, v);
1140     }
1141 }
1142 
VertexAttribI4uiv(GLuint index,const GLuint * v)1143 void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v)
1144 {
1145     EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
1146 
1147     Context *context = GetValidGlobalContext();
1148     if (context)
1149     {
1150         if (context->getClientMajorVersion() < 3)
1151         {
1152             context->handleError(Error(GL_INVALID_OPERATION));
1153             return;
1154         }
1155 
1156         if (index >= MAX_VERTEX_ATTRIBS)
1157         {
1158             context->handleError(Error(GL_INVALID_VALUE));
1159             return;
1160         }
1161 
1162         context->vertexAttribI4uiv(index, v);
1163     }
1164 }
1165 
GetUniformuiv(GLuint program,GLint location,GLuint * params)1166 void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params)
1167 {
1168     EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
1169           program, location, params);
1170 
1171     Context *context = GetValidGlobalContext();
1172     if (context)
1173     {
1174         if (!ValidateGetUniformuiv(context, program, location, params))
1175         {
1176             return;
1177         }
1178 
1179         Program *programObject = context->getProgram(program);
1180         ASSERT(programObject);
1181 
1182         programObject->getUniformuiv(location, params);
1183     }
1184 }
1185 
GetFragDataLocation(GLuint program,const GLchar * name)1186 GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
1187 {
1188     EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
1189           program, name);
1190 
1191     Context *context = GetValidGlobalContext();
1192     if (context)
1193     {
1194         if (context->getClientMajorVersion() < 3)
1195         {
1196             context->handleError(Error(GL_INVALID_OPERATION));
1197             return -1;
1198         }
1199 
1200         if (program == 0)
1201         {
1202             context->handleError(Error(GL_INVALID_VALUE));
1203             return -1;
1204         }
1205 
1206         Program *programObject = context->getProgram(program);
1207 
1208         if (!programObject || !programObject->isLinked())
1209         {
1210             context->handleError(Error(GL_INVALID_OPERATION));
1211             return -1;
1212         }
1213 
1214         return programObject->getFragDataLocation(name);
1215     }
1216 
1217     return 0;
1218 }
1219 
Uniform1ui(GLint location,GLuint v0)1220 void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
1221 {
1222     Uniform1uiv(location, 1, &v0);
1223 }
1224 
Uniform2ui(GLint location,GLuint v0,GLuint v1)1225 void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
1226 {
1227     const GLuint xy[] = { v0, v1 };
1228     Uniform2uiv(location, 1, xy);
1229 }
1230 
Uniform3ui(GLint location,GLuint v0,GLuint v1,GLuint v2)1231 void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
1232 {
1233     const GLuint xyz[] = { v0, v1, v2 };
1234     Uniform3uiv(location, 1, xyz);
1235 }
1236 
Uniform4ui(GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)1237 void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
1238 {
1239     const GLuint xyzw[] = { v0, v1, v2, v3 };
1240     Uniform4uiv(location, 1, xyzw);
1241 }
1242 
Uniform1uiv(GLint location,GLsizei count,const GLuint * value)1243 void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value)
1244 {
1245     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
1246           location, count, value);
1247 
1248     Context *context = GetValidGlobalContext();
1249     if (context)
1250     {
1251         if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
1252         {
1253             return;
1254         }
1255 
1256         Program *program = context->getGLState().getProgram();
1257         program->setUniform1uiv(location, count, value);
1258     }
1259 }
1260 
Uniform2uiv(GLint location,GLsizei count,const GLuint * value)1261 void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value)
1262 {
1263     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
1264           location, count, value);
1265 
1266     Context *context = GetValidGlobalContext();
1267     if (context)
1268     {
1269         if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
1270         {
1271             return;
1272         }
1273 
1274         Program *program = context->getGLState().getProgram();
1275         program->setUniform2uiv(location, count, value);
1276     }
1277 }
1278 
Uniform3uiv(GLint location,GLsizei count,const GLuint * value)1279 void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value)
1280 {
1281     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
1282           location, count, value);
1283 
1284     Context *context = GetValidGlobalContext();
1285     if (context)
1286     {
1287         if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
1288         {
1289             return;
1290         }
1291 
1292         Program *program = context->getGLState().getProgram();
1293         program->setUniform3uiv(location, count, value);
1294     }
1295 }
1296 
Uniform4uiv(GLint location,GLsizei count,const GLuint * value)1297 void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value)
1298 {
1299     EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
1300           location, count, value);
1301 
1302     Context *context = GetValidGlobalContext();
1303     if (context)
1304     {
1305         if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
1306         {
1307             return;
1308         }
1309 
1310         Program *program = context->getGLState().getProgram();
1311         program->setUniform4uiv(location, count, value);
1312     }
1313 }
1314 
ClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)1315 void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
1316 {
1317     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
1318           buffer, drawbuffer, value);
1319 
1320     Context *context = GetValidGlobalContext();
1321     if (context)
1322     {
1323         if (!context->skipValidation() &&
1324             !ValidateClearBufferiv(context, buffer, drawbuffer, value))
1325         {
1326             return;
1327         }
1328 
1329         context->clearBufferiv(buffer, drawbuffer, value);
1330     }
1331 }
1332 
ClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)1333 void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
1334 {
1335     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
1336           buffer, drawbuffer, value);
1337 
1338     Context *context = GetValidGlobalContext();
1339     if (context)
1340     {
1341         if (!context->skipValidation() &&
1342             !ValidateClearBufferuiv(context, buffer, drawbuffer, value))
1343         {
1344             return;
1345         }
1346 
1347         context->clearBufferuiv(buffer, drawbuffer, value);
1348     }
1349 }
1350 
ClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)1351 void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
1352 {
1353     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
1354           buffer, drawbuffer, value);
1355 
1356     Context *context = GetValidGlobalContext();
1357     if (context)
1358     {
1359         if (!context->skipValidation() &&
1360             !ValidateClearBufferfv(context, buffer, drawbuffer, value))
1361         {
1362             return;
1363         }
1364 
1365         context->clearBufferfv(buffer, drawbuffer, value);
1366     }
1367 }
1368 
ClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)1369 void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
1370 {
1371     EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
1372           buffer, drawbuffer, depth, stencil);
1373 
1374     Context *context = GetValidGlobalContext();
1375     if (context)
1376     {
1377         if (!context->skipValidation() &&
1378             !ValidateClearBufferfi(context, buffer, drawbuffer, depth, stencil))
1379         {
1380             return;
1381         }
1382 
1383         context->clearBufferfi(buffer, drawbuffer, depth, stencil);
1384     }
1385 }
1386 
GetStringi(GLenum name,GLuint index)1387 const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
1388 {
1389     EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
1390 
1391     Context *context = GetValidGlobalContext();
1392     if (context)
1393     {
1394         if (context->getClientMajorVersion() < 3)
1395         {
1396             context->handleError(Error(GL_INVALID_OPERATION));
1397             return NULL;
1398         }
1399 
1400         if (name != GL_EXTENSIONS)
1401         {
1402             context->handleError(Error(GL_INVALID_ENUM));
1403             return NULL;
1404         }
1405 
1406         if (index >= context->getExtensionStringCount())
1407         {
1408             context->handleError(Error(GL_INVALID_VALUE));
1409             return NULL;
1410         }
1411 
1412         return reinterpret_cast<const GLubyte *>(context->getExtensionString(index));
1413     }
1414 
1415     return NULL;
1416 }
1417 
CopyBufferSubData(GLenum readTarget,GLenum writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)1418 void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
1419 {
1420     EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
1421           readTarget, writeTarget, readOffset, writeOffset, size);
1422 
1423     Context *context = GetValidGlobalContext();
1424     if (context)
1425     {
1426         if (!context->skipValidation() &&
1427             !ValidateCopyBufferSubData(context, readTarget, writeTarget, readOffset, writeOffset,
1428                                        size))
1429         {
1430             return;
1431         }
1432 
1433         context->copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
1434     }
1435 }
1436 
GetUniformIndices(GLuint program,GLsizei uniformCount,const GLchar * const * uniformNames,GLuint * uniformIndices)1437 void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
1438 {
1439     EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
1440           program, uniformCount, uniformNames, uniformIndices);
1441 
1442     Context *context = GetValidGlobalContext();
1443     if (context)
1444     {
1445         if (context->getClientMajorVersion() < 3)
1446         {
1447             context->handleError(Error(GL_INVALID_OPERATION));
1448             return;
1449         }
1450 
1451         if (uniformCount < 0)
1452         {
1453             context->handleError(Error(GL_INVALID_VALUE));
1454             return;
1455         }
1456 
1457         Program *programObject = GetValidProgram(context, program);
1458 
1459         if (!programObject)
1460         {
1461             return;
1462         }
1463 
1464         if (!programObject->isLinked())
1465         {
1466             for (int uniformId = 0; uniformId < uniformCount; uniformId++)
1467             {
1468                 uniformIndices[uniformId] = GL_INVALID_INDEX;
1469             }
1470         }
1471         else
1472         {
1473             for (int uniformId = 0; uniformId < uniformCount; uniformId++)
1474             {
1475                 uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
1476             }
1477         }
1478     }
1479 }
1480 
GetActiveUniformsiv(GLuint program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,GLint * params)1481 void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
1482 {
1483     EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
1484           program, uniformCount, uniformIndices, pname, params);
1485 
1486     Context *context = GetValidGlobalContext();
1487     if (context)
1488     {
1489         if (context->getClientMajorVersion() < 3)
1490         {
1491             context->handleError(Error(GL_INVALID_OPERATION));
1492             return;
1493         }
1494 
1495         if (uniformCount < 0)
1496         {
1497             context->handleError(Error(GL_INVALID_VALUE));
1498             return;
1499         }
1500 
1501         Program *programObject = GetValidProgram(context, program);
1502 
1503         if (!programObject)
1504         {
1505             return;
1506         }
1507 
1508         switch (pname)
1509         {
1510           case GL_UNIFORM_TYPE:
1511           case GL_UNIFORM_SIZE:
1512           case GL_UNIFORM_NAME_LENGTH:
1513           case GL_UNIFORM_BLOCK_INDEX:
1514           case GL_UNIFORM_OFFSET:
1515           case GL_UNIFORM_ARRAY_STRIDE:
1516           case GL_UNIFORM_MATRIX_STRIDE:
1517           case GL_UNIFORM_IS_ROW_MAJOR:
1518             break;
1519 
1520           default:
1521               context->handleError(Error(GL_INVALID_ENUM));
1522             return;
1523         }
1524 
1525         if (uniformCount > programObject->getActiveUniformCount())
1526         {
1527             context->handleError(Error(GL_INVALID_VALUE));
1528             return;
1529         }
1530 
1531         for (int uniformId = 0; uniformId < uniformCount; uniformId++)
1532         {
1533             const GLuint index = uniformIndices[uniformId];
1534 
1535             if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
1536             {
1537                 context->handleError(Error(GL_INVALID_VALUE));
1538                 return;
1539             }
1540         }
1541 
1542         for (int uniformId = 0; uniformId < uniformCount; uniformId++)
1543         {
1544             const GLuint index = uniformIndices[uniformId];
1545             params[uniformId] = programObject->getActiveUniformi(index, pname);
1546         }
1547     }
1548 }
1549 
GetUniformBlockIndex(GLuint program,const GLchar * uniformBlockName)1550 GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
1551 {
1552     EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
1553 
1554     Context *context = GetValidGlobalContext();
1555     if (context)
1556     {
1557         if (context->getClientMajorVersion() < 3)
1558         {
1559             context->handleError(Error(GL_INVALID_OPERATION));
1560             return GL_INVALID_INDEX;
1561         }
1562 
1563         Program *programObject = GetValidProgram(context, program);
1564         if (!programObject)
1565         {
1566             return GL_INVALID_INDEX;
1567         }
1568 
1569         return programObject->getUniformBlockIndex(uniformBlockName);
1570     }
1571 
1572     return 0;
1573 }
1574 
GetActiveUniformBlockiv(GLuint program,GLuint uniformBlockIndex,GLenum pname,GLint * params)1575 void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
1576 {
1577     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
1578           program, uniformBlockIndex, pname, params);
1579 
1580     Context *context = GetValidGlobalContext();
1581     if (context)
1582     {
1583         if (!context->skipValidation() &&
1584             !ValidateGetActiveUniformBlockiv(context, program, uniformBlockIndex, pname, params))
1585         {
1586             return;
1587         }
1588 
1589         const Program *programObject = context->getProgram(program);
1590         QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
1591     }
1592 }
1593 
GetActiveUniformBlockName(GLuint program,GLuint uniformBlockIndex,GLsizei bufSize,GLsizei * length,GLchar * uniformBlockName)1594 void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
1595 {
1596     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
1597           program, uniformBlockIndex, bufSize, length, uniformBlockName);
1598 
1599     Context *context = GetValidGlobalContext();
1600     if (context)
1601     {
1602         if (context->getClientMajorVersion() < 3)
1603         {
1604             context->handleError(Error(GL_INVALID_OPERATION));
1605             return;
1606         }
1607 
1608         Program *programObject = GetValidProgram(context, program);
1609 
1610         if (!programObject)
1611         {
1612             return;
1613         }
1614 
1615         if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1616         {
1617             context->handleError(Error(GL_INVALID_VALUE));
1618             return;
1619         }
1620 
1621         programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
1622     }
1623 }
1624 
UniformBlockBinding(GLuint program,GLuint uniformBlockIndex,GLuint uniformBlockBinding)1625 void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
1626 {
1627     EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
1628           program, uniformBlockIndex, uniformBlockBinding);
1629 
1630     Context *context = GetValidGlobalContext();
1631     if (context)
1632     {
1633         if (context->getClientMajorVersion() < 3)
1634         {
1635             context->handleError(Error(GL_INVALID_OPERATION));
1636             return;
1637         }
1638 
1639         if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
1640         {
1641             context->handleError(Error(GL_INVALID_VALUE));
1642             return;
1643         }
1644 
1645         Program *programObject = GetValidProgram(context, program);
1646 
1647         if (!programObject)
1648         {
1649             return;
1650         }
1651 
1652         // if never linked, there won't be any uniform blocks
1653         if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1654         {
1655             context->handleError(Error(GL_INVALID_VALUE));
1656             return;
1657         }
1658 
1659         programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
1660     }
1661 }
1662 
DrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei instanceCount)1663 void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1664 {
1665     EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1666           mode, first, count, instanceCount);
1667 
1668     Context *context = GetValidGlobalContext();
1669     if (context)
1670     {
1671         if (context->getClientMajorVersion() < 3)
1672         {
1673             context->handleError(Error(GL_INVALID_OPERATION));
1674             return;
1675         }
1676 
1677         if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount))
1678         {
1679             return;
1680         }
1681 
1682         Error error = context->drawArraysInstanced(mode, first, count, instanceCount);
1683         if (error.isError())
1684         {
1685             context->handleError(error);
1686             return;
1687         }
1688     }
1689 }
1690 
DrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei instanceCount)1691 void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
1692 {
1693     EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
1694           mode, count, type, indices, instanceCount);
1695 
1696     Context *context = GetValidGlobalContext();
1697     if (context)
1698     {
1699         if (context->getClientMajorVersion() < 3)
1700         {
1701             context->handleError(Error(GL_INVALID_OPERATION));
1702             return;
1703         }
1704 
1705         IndexRange indexRange;
1706         if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange))
1707         {
1708             return;
1709         }
1710 
1711         Error error =
1712             context->drawElementsInstanced(mode, count, type, indices, instanceCount, indexRange);
1713         if (error.isError())
1714         {
1715             context->handleError(error);
1716             return;
1717         }
1718     }
1719 }
1720 
FenceSync_(GLenum condition,GLbitfield flags)1721 GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags)
1722 {
1723     EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
1724 
1725     Context *context = GetValidGlobalContext();
1726     if (context)
1727     {
1728         if (context->getClientMajorVersion() < 3)
1729         {
1730             context->handleError(Error(GL_INVALID_OPERATION));
1731             return 0;
1732         }
1733 
1734         if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
1735         {
1736             context->handleError(Error(GL_INVALID_ENUM));
1737             return 0;
1738         }
1739 
1740         if (flags != 0)
1741         {
1742             context->handleError(Error(GL_INVALID_VALUE));
1743             return 0;
1744         }
1745 
1746         GLsync fenceSync = context->createFenceSync();
1747 
1748         FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
1749         Error error = fenceSyncObject->set(condition, flags);
1750         if (error.isError())
1751         {
1752             context->deleteFenceSync(fenceSync);
1753             context->handleError(error);
1754             return NULL;
1755         }
1756 
1757         return fenceSync;
1758     }
1759 
1760     return NULL;
1761 }
1762 
IsSync(GLsync sync)1763 GLboolean GL_APIENTRY IsSync(GLsync sync)
1764 {
1765     EVENT("(GLsync sync = 0x%0.8p)", sync);
1766 
1767     Context *context = GetValidGlobalContext();
1768     if (context)
1769     {
1770         if (context->getClientMajorVersion() < 3)
1771         {
1772             context->handleError(Error(GL_INVALID_OPERATION));
1773             return GL_FALSE;
1774         }
1775 
1776         return (context->getFenceSync(sync) != NULL);
1777     }
1778 
1779     return GL_FALSE;
1780 }
1781 
DeleteSync(GLsync sync)1782 void GL_APIENTRY DeleteSync(GLsync sync)
1783 {
1784     EVENT("(GLsync sync = 0x%0.8p)", sync);
1785 
1786     Context *context = GetValidGlobalContext();
1787     if (context)
1788     {
1789         if (context->getClientMajorVersion() < 3)
1790         {
1791             context->handleError(Error(GL_INVALID_OPERATION));
1792             return;
1793         }
1794 
1795         if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
1796         {
1797             context->handleError(Error(GL_INVALID_VALUE));
1798             return;
1799         }
1800 
1801         context->deleteFenceSync(sync);
1802     }
1803 }
1804 
ClientWaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)1805 GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
1806 {
1807     EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
1808           sync, flags, timeout);
1809 
1810     Context *context = GetValidGlobalContext();
1811     if (context)
1812     {
1813         if (context->getClientMajorVersion() < 3)
1814         {
1815             context->handleError(Error(GL_INVALID_OPERATION));
1816             return GL_WAIT_FAILED;
1817         }
1818 
1819         if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
1820         {
1821             context->handleError(Error(GL_INVALID_VALUE));
1822             return GL_WAIT_FAILED;
1823         }
1824 
1825         FenceSync *fenceSync = context->getFenceSync(sync);
1826 
1827         if (!fenceSync)
1828         {
1829             context->handleError(Error(GL_INVALID_VALUE));
1830             return GL_WAIT_FAILED;
1831         }
1832 
1833         GLenum result = GL_WAIT_FAILED;
1834         Error error = fenceSync->clientWait(flags, timeout, &result);
1835         if (error.isError())
1836         {
1837             context->handleError(error);
1838             return GL_WAIT_FAILED;
1839         }
1840 
1841         return result;
1842     }
1843 
1844     return GL_FALSE;
1845 }
1846 
WaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)1847 void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
1848 {
1849     EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
1850           sync, flags, timeout);
1851 
1852     Context *context = GetValidGlobalContext();
1853     if (context)
1854     {
1855         if (context->getClientMajorVersion() < 3)
1856         {
1857             context->handleError(Error(GL_INVALID_OPERATION));
1858             return;
1859         }
1860 
1861         if (flags != 0)
1862         {
1863             context->handleError(Error(GL_INVALID_VALUE));
1864             return;
1865         }
1866 
1867         if (timeout != GL_TIMEOUT_IGNORED)
1868         {
1869             context->handleError(Error(GL_INVALID_VALUE));
1870             return;
1871         }
1872 
1873         FenceSync *fenceSync = context->getFenceSync(sync);
1874 
1875         if (!fenceSync)
1876         {
1877             context->handleError(Error(GL_INVALID_VALUE));
1878             return;
1879         }
1880 
1881         Error error = fenceSync->serverWait(flags, timeout);
1882         if (error.isError())
1883         {
1884             context->handleError(error);
1885         }
1886     }
1887 }
1888 
GetInteger64v(GLenum pname,GLint64 * params)1889 void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params)
1890 {
1891     EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
1892           pname, params);
1893 
1894     Context *context = GetValidGlobalContext();
1895     if (context)
1896     {
1897         if (context->getClientMajorVersion() < 3)
1898         {
1899             context->handleError(Error(GL_INVALID_OPERATION));
1900             return;
1901         }
1902 
1903         GLenum nativeType;
1904         unsigned int numParams = 0;
1905         if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
1906         {
1907             return;
1908         }
1909 
1910         if (nativeType == GL_INT_64_ANGLEX)
1911         {
1912             context->getInteger64v(pname, params);
1913         }
1914         else
1915         {
1916             CastStateValues(context, nativeType, pname, numParams, params);
1917         }
1918     }
1919 }
1920 
GetSynciv(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)1921 void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
1922 {
1923     EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
1924           sync, pname, bufSize, length, values);
1925 
1926     Context *context = GetValidGlobalContext();
1927     if (context)
1928     {
1929         if (context->getClientMajorVersion() < 3)
1930         {
1931             context->handleError(Error(GL_INVALID_OPERATION));
1932             return;
1933         }
1934 
1935         if (bufSize < 0)
1936         {
1937             context->handleError(Error(GL_INVALID_VALUE));
1938             return;
1939         }
1940 
1941         FenceSync *fenceSync = context->getFenceSync(sync);
1942 
1943         if (!fenceSync)
1944         {
1945             context->handleError(Error(GL_INVALID_VALUE));
1946             return;
1947         }
1948 
1949         switch (pname)
1950         {
1951           case GL_OBJECT_TYPE:     values[0] = static_cast<GLint>(GL_SYNC_FENCE);              break;
1952           case GL_SYNC_CONDITION:  values[0] = static_cast<GLint>(fenceSync->getCondition());  break;
1953           case GL_SYNC_FLAGS:      values[0] = static_cast<GLint>(fenceSync->getFlags());      break;
1954 
1955           case GL_SYNC_STATUS:
1956             {
1957                 Error error = fenceSync->getStatus(values);
1958                 if (error.isError())
1959                 {
1960                     context->handleError(error);
1961                     return;
1962                 }
1963                 break;
1964             }
1965 
1966           default:
1967               context->handleError(Error(GL_INVALID_ENUM));
1968             return;
1969         }
1970     }
1971 }
1972 
GetInteger64i_v(GLenum target,GLuint index,GLint64 * data)1973 void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
1974 {
1975     EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
1976           target, index, data);
1977 
1978     Context *context = GetValidGlobalContext();
1979     if (context)
1980     {
1981         if (!context->skipValidation() && !ValidateGetInteger64i_v(context, target, index, data))
1982         {
1983             return;
1984         }
1985         context->getInteger64i_v(target, index, data);
1986     }
1987 }
1988 
GetBufferParameteri64v(GLenum target,GLenum pname,GLint64 * params)1989 void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
1990 {
1991     EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
1992           target, pname, params);
1993 
1994     Context *context = GetValidGlobalContext();
1995     if (context)
1996     {
1997         if (!context->skipValidation() &&
1998             !ValidateGetBufferParameteri64v(context, target, pname, params))
1999         {
2000             return;
2001         }
2002 
2003         Buffer *buffer = context->getGLState().getTargetBuffer(target);
2004         QueryBufferParameteri64v(buffer, pname, params);
2005     }
2006 }
2007 
GenSamplers(GLsizei count,GLuint * samplers)2008 void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers)
2009 {
2010     EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
2011 
2012     Context *context = GetValidGlobalContext();
2013     if (context)
2014     {
2015         if (!context->skipValidation() && !ValidateGenSamplers(context, count, samplers))
2016         {
2017             return;
2018         }
2019 
2020         for (int i = 0; i < count; i++)
2021         {
2022             samplers[i] = context->createSampler();
2023         }
2024     }
2025 }
2026 
DeleteSamplers(GLsizei count,const GLuint * samplers)2027 void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers)
2028 {
2029     EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
2030 
2031     Context *context = GetValidGlobalContext();
2032     if (context)
2033     {
2034         if (!context->skipValidation() && !ValidateDeleteSamplers(context, count, samplers))
2035         {
2036             return;
2037         }
2038 
2039         for (int i = 0; i < count; i++)
2040         {
2041             context->deleteSampler(samplers[i]);
2042         }
2043     }
2044 }
2045 
IsSampler(GLuint sampler)2046 GLboolean GL_APIENTRY IsSampler(GLuint sampler)
2047 {
2048     EVENT("(GLuint sampler = %u)", sampler);
2049 
2050     Context *context = GetValidGlobalContext();
2051     if (context)
2052     {
2053         if (context->getClientMajorVersion() < 3)
2054         {
2055             context->handleError(Error(GL_INVALID_OPERATION));
2056             return GL_FALSE;
2057         }
2058 
2059         return context->isSampler(sampler);
2060     }
2061 
2062     return GL_FALSE;
2063 }
2064 
BindSampler(GLuint unit,GLuint sampler)2065 void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
2066 {
2067     EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
2068 
2069     Context *context = GetValidGlobalContext();
2070     if (context)
2071     {
2072         if (context->getClientMajorVersion() < 3)
2073         {
2074             context->handleError(Error(GL_INVALID_OPERATION));
2075             return;
2076         }
2077 
2078         if (sampler != 0 && !context->isSampler(sampler))
2079         {
2080             context->handleError(Error(GL_INVALID_OPERATION));
2081             return;
2082         }
2083 
2084         if (unit >= context->getCaps().maxCombinedTextureImageUnits)
2085         {
2086             context->handleError(Error(GL_INVALID_VALUE));
2087             return;
2088         }
2089 
2090         context->bindSampler(unit, sampler);
2091     }
2092 }
2093 
SamplerParameteri(GLuint sampler,GLenum pname,GLint param)2094 void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
2095 {
2096     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
2097 
2098     Context *context = GetValidGlobalContext();
2099     if (context)
2100     {
2101         if (!context->skipValidation() &&
2102             !ValidateSamplerParameteri(context, sampler, pname, param))
2103         {
2104             return;
2105         }
2106 
2107         context->samplerParameteri(sampler, pname, param);
2108     }
2109 }
2110 
SamplerParameteriv(GLuint sampler,GLenum pname,const GLint * param)2111 void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
2112 {
2113     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLint* params = 0x%0.8p)", sampler,
2114           pname, param);
2115 
2116     Context *context = GetValidGlobalContext();
2117     if (context)
2118     {
2119         if (!context->skipValidation() &&
2120             !ValidateSamplerParameteriv(context, sampler, pname, param))
2121         {
2122             return;
2123         }
2124 
2125         context->samplerParameteriv(sampler, pname, param);
2126     }
2127 }
2128 
SamplerParameterf(GLuint sampler,GLenum pname,GLfloat param)2129 void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
2130 {
2131     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
2132 
2133     Context *context = GetValidGlobalContext();
2134     if (context)
2135     {
2136         if (!context->skipValidation() &&
2137             !ValidateSamplerParameterf(context, sampler, pname, param))
2138         {
2139             return;
2140         }
2141 
2142         context->samplerParameterf(sampler, pname, param);
2143     }
2144 }
2145 
SamplerParameterfv(GLuint sampler,GLenum pname,const GLfloat * param)2146 void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
2147 {
2148     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLfloat* params = 0x%0.8p)", sampler,
2149           pname, param);
2150 
2151     Context *context = GetValidGlobalContext();
2152     if (context)
2153     {
2154         if (!context->skipValidation() &&
2155             !ValidateSamplerParameterfv(context, sampler, pname, param))
2156         {
2157             return;
2158         }
2159 
2160         context->samplerParameterfv(sampler, pname, param);
2161     }
2162 }
2163 
GetSamplerParameteriv(GLuint sampler,GLenum pname,GLint * params)2164 void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
2165 {
2166     EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname,
2167           params);
2168 
2169     Context *context = GetValidGlobalContext();
2170     if (context)
2171     {
2172         if (!context->skipValidation() &&
2173             !ValidateGetSamplerParameteriv(context, sampler, pname, params))
2174         {
2175             return;
2176         }
2177 
2178         context->getSamplerParameteriv(sampler, pname, params);
2179     }
2180 }
2181 
GetSamplerParameterfv(GLuint sampler,GLenum pname,GLfloat * params)2182 void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
2183 {
2184     EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
2185 
2186     Context *context = GetValidGlobalContext();
2187     if (context)
2188     {
2189         if (!context->skipValidation() &&
2190             !ValidateGetSamplerParameterfv(context, sampler, pname, params))
2191         {
2192             return;
2193         }
2194 
2195         context->getSamplerParameterfv(sampler, pname, params);
2196     }
2197 }
2198 
VertexAttribDivisor(GLuint index,GLuint divisor)2199 void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
2200 {
2201     EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
2202 
2203     Context *context = GetValidGlobalContext();
2204     if (context)
2205     {
2206         if (context->getClientMajorVersion() < 3)
2207         {
2208             context->handleError(Error(GL_INVALID_OPERATION));
2209             return;
2210         }
2211 
2212         if (index >= MAX_VERTEX_ATTRIBS)
2213         {
2214             context->handleError(Error(GL_INVALID_VALUE));
2215             return;
2216         }
2217 
2218         context->setVertexAttribDivisor(index, divisor);
2219     }
2220 }
2221 
BindTransformFeedback(GLenum target,GLuint id)2222 void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
2223 {
2224     EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
2225 
2226     Context *context = GetValidGlobalContext();
2227     if (context)
2228     {
2229         if (context->getClientMajorVersion() < 3)
2230         {
2231             context->handleError(Error(GL_INVALID_OPERATION));
2232             return;
2233         }
2234 
2235         switch (target)
2236         {
2237           case GL_TRANSFORM_FEEDBACK:
2238             {
2239                 // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
2240                 TransformFeedback *curTransformFeedback =
2241                     context->getGLState().getCurrentTransformFeedback();
2242                 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
2243                 {
2244                     context->handleError(Error(GL_INVALID_OPERATION));
2245                     return;
2246                 }
2247 
2248                 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
2249                 if (!context->isTransformFeedbackGenerated(id))
2250                 {
2251                     context->handleError(
2252                         Error(GL_INVALID_OPERATION,
2253                               "Cannot bind a transform feedback object that does not exist."));
2254                     return;
2255                 }
2256 
2257                 context->bindTransformFeedback(id);
2258             }
2259             break;
2260 
2261           default:
2262               context->handleError(Error(GL_INVALID_ENUM));
2263             return;
2264         }
2265     }
2266 }
2267 
DeleteTransformFeedbacks(GLsizei n,const GLuint * ids)2268 void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
2269 {
2270     EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
2271 
2272     Context *context = GetValidGlobalContext();
2273     if (context)
2274     {
2275         if (!context->skipValidation() && !ValidateDeleteTransformFeedbacks(context, n, ids))
2276         {
2277             return;
2278         }
2279 
2280         for (int i = 0; i < n; i++)
2281         {
2282             context->deleteTransformFeedback(ids[i]);
2283         }
2284     }
2285 }
2286 
GenTransformFeedbacks(GLsizei n,GLuint * ids)2287 void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids)
2288 {
2289     EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
2290 
2291     Context *context = GetValidGlobalContext();
2292     if (context)
2293     {
2294         if (!context->skipValidation() && !ValidateGenTransformFeedbacks(context, n, ids))
2295         {
2296             return;
2297         }
2298 
2299         for (int i = 0; i < n; i++)
2300         {
2301             ids[i] = context->createTransformFeedback();
2302         }
2303     }
2304 }
2305 
IsTransformFeedback(GLuint id)2306 GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
2307 {
2308     EVENT("(GLuint id = %u)", id);
2309 
2310     Context *context = GetValidGlobalContext();
2311     if (context)
2312     {
2313         if (context->getClientMajorVersion() < 3)
2314         {
2315             context->handleError(Error(GL_INVALID_OPERATION));
2316             return GL_FALSE;
2317         }
2318 
2319         if (id == 0)
2320         {
2321             // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
2322             // returns FALSE
2323             return GL_FALSE;
2324         }
2325 
2326         const TransformFeedback *transformFeedback = context->getTransformFeedback(id);
2327         return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
2328     }
2329 
2330     return GL_FALSE;
2331 }
2332 
PauseTransformFeedback(void)2333 void GL_APIENTRY PauseTransformFeedback(void)
2334 {
2335     EVENT("(void)");
2336 
2337     Context *context = GetValidGlobalContext();
2338     if (context)
2339     {
2340         if (context->getClientMajorVersion() < 3)
2341         {
2342             context->handleError(Error(GL_INVALID_OPERATION));
2343             return;
2344         }
2345 
2346         TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2347         ASSERT(transformFeedback != NULL);
2348 
2349         // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
2350         if (!transformFeedback->isActive() || transformFeedback->isPaused())
2351         {
2352             context->handleError(Error(GL_INVALID_OPERATION));
2353             return;
2354         }
2355 
2356         transformFeedback->pause();
2357     }
2358 }
2359 
ResumeTransformFeedback(void)2360 void GL_APIENTRY ResumeTransformFeedback(void)
2361 {
2362     EVENT("(void)");
2363 
2364     Context *context = GetValidGlobalContext();
2365     if (context)
2366     {
2367         if (context->getClientMajorVersion() < 3)
2368         {
2369             context->handleError(Error(GL_INVALID_OPERATION));
2370             return;
2371         }
2372 
2373         TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2374         ASSERT(transformFeedback != NULL);
2375 
2376         // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
2377         if (!transformFeedback->isActive() || !transformFeedback->isPaused())
2378         {
2379             context->handleError(Error(GL_INVALID_OPERATION));
2380             return;
2381         }
2382 
2383         transformFeedback->resume();
2384     }
2385 }
2386 
GetProgramBinary(GLuint program,GLsizei bufSize,GLsizei * length,GLenum * binaryFormat,GLvoid * binary)2387 void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
2388 {
2389     EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
2390           program, bufSize, length, binaryFormat, binary);
2391 
2392     Context *context = GetValidGlobalContext();
2393     if (context)
2394     {
2395         if (!ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
2396         {
2397             return;
2398         }
2399 
2400         Program *programObject = context->getProgram(program);
2401         ASSERT(programObject != nullptr);
2402 
2403         Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
2404         if (error.isError())
2405         {
2406             context->handleError(error);
2407             return;
2408         }
2409     }
2410 }
2411 
ProgramBinary(GLuint program,GLenum binaryFormat,const GLvoid * binary,GLsizei length)2412 void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
2413 {
2414     EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
2415           program, binaryFormat, binary, length);
2416 
2417     Context *context = GetValidGlobalContext();
2418     if (context)
2419     {
2420         if (!ValidateProgramBinary(context, program, binaryFormat, binary, length))
2421         {
2422             return;
2423         }
2424 
2425         Program *programObject = context->getProgram(program);
2426         ASSERT(programObject != nullptr);
2427 
2428         Error error = programObject->loadBinary(binaryFormat, binary, length);
2429         if (error.isError())
2430         {
2431             context->handleError(error);
2432             return;
2433         }
2434     }
2435 }
2436 
ProgramParameteri(GLuint program,GLenum pname,GLint value)2437 void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
2438 {
2439     EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
2440           program, pname, value);
2441 
2442     Context *context = GetValidGlobalContext();
2443     if (context)
2444     {
2445         if (!context->skipValidation() &&
2446             !ValidateProgramParameteri(context, program, pname, value))
2447         {
2448             return;
2449         }
2450 
2451         context->programParameteri(program, pname, value);
2452     }
2453 }
2454 
InvalidateFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments)2455 void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
2456 {
2457     EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
2458           target, numAttachments, attachments);
2459 
2460     Context *context = GetValidGlobalContext();
2461     if (context)
2462     {
2463         if (!context->skipValidation() &&
2464             !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
2465         {
2466             return;
2467         }
2468 
2469         context->invalidateFramebuffer(target, numAttachments, attachments);
2470     }
2471 }
2472 
InvalidateSubFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)2473 void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
2474 {
2475     EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
2476           "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
2477           target, numAttachments, attachments, x, y, width, height);
2478 
2479     Context *context = GetValidGlobalContext();
2480     if (context)
2481     {
2482         if (!context->skipValidation() &&
2483             !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
2484         {
2485             return;
2486         }
2487 
2488         context->invalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
2489     }
2490 }
2491 
TexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)2492 void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
2493 {
2494     EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
2495           target, levels, internalformat, width, height);
2496 
2497     Context *context = GetValidGlobalContext();
2498     if (context)
2499     {
2500         if (context->getClientMajorVersion() < 3)
2501         {
2502             context->handleError(Error(GL_INVALID_OPERATION));
2503             return;
2504         }
2505 
2506         if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width,
2507                                                height, 1))
2508         {
2509             return;
2510         }
2511 
2512         Extents size(width, height, 1);
2513         Texture *texture = context->getTargetTexture(target);
2514         Error error = texture->setStorage(target, levels, internalformat, size);
2515         if (error.isError())
2516         {
2517             context->handleError(error);
2518             return;
2519         }
2520     }
2521 }
2522 
TexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)2523 void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
2524 {
2525     EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
2526           "GLsizei height = %d, GLsizei depth = %d)",
2527           target, levels, internalformat, width, height, depth);
2528 
2529     Context *context = GetValidGlobalContext();
2530     if (context)
2531     {
2532         if (context->getClientMajorVersion() < 3)
2533         {
2534             context->handleError(Error(GL_INVALID_OPERATION));
2535             return;
2536         }
2537 
2538         if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width,
2539                                                height, depth))
2540         {
2541             return;
2542         }
2543 
2544         Extents size(width, height, depth);
2545         Texture *texture = context->getTargetTexture(target);
2546         Error error = texture->setStorage(target, levels, internalformat, size);
2547         if (error.isError())
2548         {
2549             context->handleError(error);
2550             return;
2551         }
2552     }
2553 }
2554 
GetInternalformativ(GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLint * params)2555 void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
2556 {
2557     EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
2558           "GLint* params = 0x%0.8p)",
2559           target, internalformat, pname, bufSize, params);
2560 
2561     Context *context = GetValidGlobalContext();
2562     if (context)
2563     {
2564         if (!context->skipValidation() &&
2565             !ValidateGetInternalFormativ(context, target, internalformat, pname, bufSize, params))
2566         {
2567             return;
2568         }
2569 
2570         const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2571         QueryInternalFormativ(formatCaps, pname, bufSize, params);
2572     }
2573 }
2574 
2575 }
2576