1 //
2 // Copyright 2016 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 // validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
8 
9 #include "libANGLE/validationES31_autogen.h"
10 
11 #include "libANGLE/Context.h"
12 #include "libANGLE/ErrorStrings.h"
13 #include "libANGLE/Framebuffer.h"
14 #include "libANGLE/ProgramExecutable.h"
15 #include "libANGLE/VertexArray.h"
16 #include "libANGLE/validationES.h"
17 #include "libANGLE/validationES2_autogen.h"
18 #include "libANGLE/validationES31.h"
19 #include "libANGLE/validationES3_autogen.h"
20 
21 #include "common/utilities.h"
22 
23 using namespace angle;
24 
25 namespace gl
26 {
27 using namespace err;
28 
29 namespace
30 {
31 
ValidateNamedProgramInterface(GLenum programInterface)32 bool ValidateNamedProgramInterface(GLenum programInterface)
33 {
34     switch (programInterface)
35     {
36         case GL_UNIFORM:
37         case GL_UNIFORM_BLOCK:
38         case GL_PROGRAM_INPUT:
39         case GL_PROGRAM_OUTPUT:
40         case GL_TRANSFORM_FEEDBACK_VARYING:
41         case GL_BUFFER_VARIABLE:
42         case GL_SHADER_STORAGE_BLOCK:
43             return true;
44         default:
45             return false;
46     }
47 }
48 
ValidateLocationProgramInterface(GLenum programInterface)49 bool ValidateLocationProgramInterface(GLenum programInterface)
50 {
51     switch (programInterface)
52     {
53         case GL_UNIFORM:
54         case GL_PROGRAM_INPUT:
55         case GL_PROGRAM_OUTPUT:
56             return true;
57         default:
58             return false;
59     }
60 }
61 
ValidateProgramInterface(GLenum programInterface)62 bool ValidateProgramInterface(GLenum programInterface)
63 {
64     return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
65             ValidateNamedProgramInterface(programInterface));
66 }
67 
ValidateProgramResourceProperty(const Context * context,GLenum prop)68 bool ValidateProgramResourceProperty(const Context *context, GLenum prop)
69 {
70     ASSERT(context);
71     switch (prop)
72     {
73         case GL_ACTIVE_VARIABLES:
74         case GL_BUFFER_BINDING:
75         case GL_NUM_ACTIVE_VARIABLES:
76 
77         case GL_ARRAY_SIZE:
78 
79         case GL_ARRAY_STRIDE:
80         case GL_BLOCK_INDEX:
81         case GL_IS_ROW_MAJOR:
82         case GL_MATRIX_STRIDE:
83 
84         case GL_ATOMIC_COUNTER_BUFFER_INDEX:
85 
86         case GL_BUFFER_DATA_SIZE:
87 
88         case GL_LOCATION:
89 
90         case GL_NAME_LENGTH:
91 
92         case GL_OFFSET:
93 
94         case GL_REFERENCED_BY_VERTEX_SHADER:
95         case GL_REFERENCED_BY_FRAGMENT_SHADER:
96         case GL_REFERENCED_BY_COMPUTE_SHADER:
97 
98         case GL_TOP_LEVEL_ARRAY_SIZE:
99         case GL_TOP_LEVEL_ARRAY_STRIDE:
100 
101         case GL_TYPE:
102             return true;
103 
104         case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
105             return context->getExtensions().geometryShader;
106 
107         case GL_LOCATION_INDEX_EXT:
108             return context->getExtensions().blendFuncExtended;
109 
110         default:
111             return false;
112     }
113 }
114 
115 // GLES 3.10 spec: Page 82 -- Table 7.2
ValidateProgramResourcePropertyByInterface(GLenum prop,GLenum programInterface)116 bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
117 {
118     switch (prop)
119     {
120         case GL_ACTIVE_VARIABLES:
121         case GL_BUFFER_BINDING:
122         case GL_NUM_ACTIVE_VARIABLES:
123         {
124             switch (programInterface)
125             {
126                 case GL_ATOMIC_COUNTER_BUFFER:
127                 case GL_SHADER_STORAGE_BLOCK:
128                 case GL_UNIFORM_BLOCK:
129                     return true;
130                 default:
131                     return false;
132             }
133         }
134 
135         case GL_ARRAY_SIZE:
136         {
137             switch (programInterface)
138             {
139                 case GL_BUFFER_VARIABLE:
140                 case GL_PROGRAM_INPUT:
141                 case GL_PROGRAM_OUTPUT:
142                 case GL_TRANSFORM_FEEDBACK_VARYING:
143                 case GL_UNIFORM:
144                     return true;
145                 default:
146                     return false;
147             }
148         }
149 
150         case GL_ARRAY_STRIDE:
151         case GL_BLOCK_INDEX:
152         case GL_IS_ROW_MAJOR:
153         case GL_MATRIX_STRIDE:
154         {
155             switch (programInterface)
156             {
157                 case GL_BUFFER_VARIABLE:
158                 case GL_UNIFORM:
159                     return true;
160                 default:
161                     return false;
162             }
163         }
164 
165         case GL_ATOMIC_COUNTER_BUFFER_INDEX:
166         {
167             if (programInterface == GL_UNIFORM)
168             {
169                 return true;
170             }
171             return false;
172         }
173 
174         case GL_BUFFER_DATA_SIZE:
175         {
176             switch (programInterface)
177             {
178                 case GL_ATOMIC_COUNTER_BUFFER:
179                 case GL_SHADER_STORAGE_BLOCK:
180                 case GL_UNIFORM_BLOCK:
181                     return true;
182                 default:
183                     return false;
184             }
185         }
186 
187         case GL_LOCATION:
188         {
189             return ValidateLocationProgramInterface(programInterface);
190         }
191 
192         case GL_LOCATION_INDEX_EXT:
193         {
194             // EXT_blend_func_extended
195             return (programInterface == GL_PROGRAM_OUTPUT);
196         }
197 
198         case GL_NAME_LENGTH:
199         {
200             return ValidateNamedProgramInterface(programInterface);
201         }
202 
203         case GL_OFFSET:
204         {
205             switch (programInterface)
206             {
207                 case GL_BUFFER_VARIABLE:
208                 case GL_UNIFORM:
209                     return true;
210                 default:
211                     return false;
212             }
213         }
214 
215         case GL_REFERENCED_BY_VERTEX_SHADER:
216         case GL_REFERENCED_BY_FRAGMENT_SHADER:
217         case GL_REFERENCED_BY_COMPUTE_SHADER:
218         case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
219         {
220             switch (programInterface)
221             {
222                 case GL_ATOMIC_COUNTER_BUFFER:
223                 case GL_BUFFER_VARIABLE:
224                 case GL_PROGRAM_INPUT:
225                 case GL_PROGRAM_OUTPUT:
226                 case GL_SHADER_STORAGE_BLOCK:
227                 case GL_UNIFORM:
228                 case GL_UNIFORM_BLOCK:
229                     return true;
230                 default:
231                     return false;
232             }
233         }
234 
235         case GL_TOP_LEVEL_ARRAY_SIZE:
236         case GL_TOP_LEVEL_ARRAY_STRIDE:
237         {
238             if (programInterface == GL_BUFFER_VARIABLE)
239             {
240                 return true;
241             }
242             return false;
243         }
244 
245         case GL_TYPE:
246         {
247             switch (programInterface)
248             {
249                 case GL_BUFFER_VARIABLE:
250                 case GL_PROGRAM_INPUT:
251                 case GL_PROGRAM_OUTPUT:
252                 case GL_TRANSFORM_FEEDBACK_VARYING:
253                 case GL_UNIFORM:
254                     return true;
255                 default:
256                     return false;
257             }
258         }
259 
260         default:
261             return false;
262     }
263 }
264 
ValidateProgramResourceIndex(const Program * programObject,GLenum programInterface,GLuint index)265 bool ValidateProgramResourceIndex(const Program *programObject,
266                                   GLenum programInterface,
267                                   GLuint index)
268 {
269     switch (programInterface)
270     {
271         case GL_PROGRAM_INPUT:
272             return (index <
273                     static_cast<GLuint>(programObject->getState().getProgramInputs().size()));
274 
275         case GL_PROGRAM_OUTPUT:
276             return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
277 
278         case GL_UNIFORM:
279             return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
280 
281         case GL_BUFFER_VARIABLE:
282             return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
283 
284         case GL_SHADER_STORAGE_BLOCK:
285             return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
286 
287         case GL_UNIFORM_BLOCK:
288             return (index < programObject->getActiveUniformBlockCount());
289 
290         case GL_ATOMIC_COUNTER_BUFFER:
291             return (index < programObject->getActiveAtomicCounterBufferCount());
292 
293         case GL_TRANSFORM_FEEDBACK_VARYING:
294             return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
295 
296         default:
297             UNREACHABLE();
298             return false;
299     }
300 }
301 
ValidateProgramUniform(const Context * context,GLenum valueType,ShaderProgramID program,UniformLocation location,GLsizei count)302 bool ValidateProgramUniform(const Context *context,
303                             GLenum valueType,
304                             ShaderProgramID program,
305                             UniformLocation location,
306                             GLsizei count)
307 {
308     // Check for ES31 program uniform entry points
309     if (context->getClientVersion() < Version(3, 1))
310     {
311         context->validationError(GL_INVALID_OPERATION, kES31Required);
312         return false;
313     }
314 
315     const LinkedUniform *uniform = nullptr;
316     Program *programObject       = GetValidProgram(context, program);
317     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
318            ValidateUniformValue(context, valueType, uniform->type);
319 }
320 
ValidateProgramUniformMatrix(const Context * context,GLenum valueType,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose)321 bool ValidateProgramUniformMatrix(const Context *context,
322                                   GLenum valueType,
323                                   ShaderProgramID program,
324                                   UniformLocation location,
325                                   GLsizei count,
326                                   GLboolean transpose)
327 {
328     // Check for ES31 program uniform entry points
329     if (context->getClientVersion() < Version(3, 1))
330     {
331         context->validationError(GL_INVALID_OPERATION, kES31Required);
332         return false;
333     }
334 
335     const LinkedUniform *uniform = nullptr;
336     Program *programObject       = GetValidProgram(context, program);
337     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
338            ValidateUniformMatrixValue(context, valueType, uniform->type);
339 }
340 
ValidateVertexAttribFormatCommon(const Context * context,GLuint relativeOffset)341 bool ValidateVertexAttribFormatCommon(const Context *context, GLuint relativeOffset)
342 {
343     if (context->getClientVersion() < ES_3_1)
344     {
345         context->validationError(GL_INVALID_OPERATION, kES31Required);
346         return false;
347     }
348 
349     const Caps &caps = context->getCaps();
350     if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
351     {
352         context->validationError(GL_INVALID_VALUE, kRelativeOffsetTooLarge);
353         return false;
354     }
355 
356     // [OpenGL ES 3.1] Section 10.3.1 page 243:
357     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
358     if (context->getState().getVertexArrayId().value == 0)
359     {
360         context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
361         return false;
362     }
363 
364     return true;
365 }
366 
367 }  // anonymous namespace
368 
ValidateGetBooleani_v(const Context * context,GLenum target,GLuint index,const GLboolean * data)369 bool ValidateGetBooleani_v(const Context *context,
370                            GLenum target,
371                            GLuint index,
372                            const GLboolean *data)
373 {
374     if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
375     {
376         context->validationError(GL_INVALID_OPERATION,
377                                  kES31OrDrawBuffersIndexedExtensionNotAvailable);
378         return false;
379     }
380 
381     if (!ValidateIndexedStateQuery(context, target, index, nullptr))
382     {
383         return false;
384     }
385 
386     return true;
387 }
388 
ValidateGetBooleani_vRobustANGLE(const Context * context,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLboolean * data)389 bool ValidateGetBooleani_vRobustANGLE(const Context *context,
390                                       GLenum target,
391                                       GLuint index,
392                                       GLsizei bufSize,
393                                       const GLsizei *length,
394                                       const GLboolean *data)
395 {
396     if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
397     {
398         context->validationError(GL_INVALID_OPERATION,
399                                  kES31OrDrawBuffersIndexedExtensionNotAvailable);
400         return false;
401     }
402 
403     if (!ValidateRobustEntryPoint(context, bufSize))
404     {
405         return false;
406     }
407 
408     GLsizei numParams = 0;
409 
410     if (!ValidateIndexedStateQuery(context, target, index, &numParams))
411     {
412         return false;
413     }
414 
415     if (!ValidateRobustBufferSize(context, bufSize, numParams))
416     {
417         return false;
418     }
419 
420     SetRobustLengthParam(length, numParams);
421     return true;
422 }
423 
ValidateDrawIndirectBase(const Context * context,PrimitiveMode mode,const void * indirect)424 bool ValidateDrawIndirectBase(const Context *context, PrimitiveMode mode, const void *indirect)
425 {
426     if (context->getClientVersion() < ES_3_1)
427     {
428         context->validationError(GL_INVALID_OPERATION, kES31Required);
429         return false;
430     }
431 
432     // Here the third parameter 1 is only to pass the count validation.
433     if (!ValidateDrawBase(context, mode))
434     {
435         return false;
436     }
437 
438     const State &state = context->getState();
439 
440     // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
441     // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
442     if (state.getVertexArrayId().value == 0)
443     {
444         context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
445         return false;
446     }
447 
448     if (context->getStateCache().hasAnyActiveClientAttrib())
449     {
450         context->validationError(GL_INVALID_OPERATION, kClientDataInVertexArray);
451         return false;
452     }
453 
454     Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
455     if (!drawIndirectBuffer)
456     {
457         context->validationError(GL_INVALID_OPERATION, kDrawIndirectBufferNotBound);
458         return false;
459     }
460 
461     // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
462     // machine units, of uint.
463     GLint64 offset = reinterpret_cast<GLint64>(indirect);
464     if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
465     {
466         context->validationError(GL_INVALID_VALUE, kInvalidIndirectOffset);
467         return false;
468     }
469 
470     return true;
471 }
472 
ValidateDrawArraysIndirect(const Context * context,PrimitiveMode mode,const void * indirect)473 bool ValidateDrawArraysIndirect(const Context *context, PrimitiveMode mode, const void *indirect)
474 {
475     const State &state                      = context->getState();
476     TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
477     if (curTransformFeedback && curTransformFeedback->isActive() &&
478         !curTransformFeedback->isPaused())
479     {
480         // EXT_geometry_shader allows transform feedback to work with all draw commands.
481         // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
482         if (context->getExtensions().geometryShader)
483         {
484             if (!ValidateTransformFeedbackPrimitiveMode(
485                     context, curTransformFeedback->getPrimitiveMode(), mode))
486             {
487                 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
488                 return false;
489             }
490         }
491         else
492         {
493             // An INVALID_OPERATION error is generated if transform feedback is active and not
494             // paused.
495             context->validationError(GL_INVALID_OPERATION,
496                                      kUnsupportedDrawModeForTransformFeedback);
497             return false;
498         }
499     }
500 
501     if (!ValidateDrawIndirectBase(context, mode, indirect))
502         return false;
503 
504     Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
505     CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
506     // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
507     // which's size is 4 * sizeof(uint).
508     auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
509     if (!checkedSum.IsValid() ||
510         checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
511     {
512         context->validationError(GL_INVALID_OPERATION, kParamOverflow);
513         return false;
514     }
515 
516     return true;
517 }
518 
ValidateDrawElementsIndirect(const Context * context,PrimitiveMode mode,DrawElementsType type,const void * indirect)519 bool ValidateDrawElementsIndirect(const Context *context,
520                                   PrimitiveMode mode,
521                                   DrawElementsType type,
522                                   const void *indirect)
523 {
524     if (!ValidateDrawElementsBase(context, mode, type))
525     {
526         return false;
527     }
528 
529     const State &state         = context->getState();
530     const VertexArray *vao     = state.getVertexArray();
531     Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
532     if (!elementArrayBuffer)
533     {
534         context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
535         return false;
536     }
537 
538     if (!ValidateDrawIndirectBase(context, mode, indirect))
539         return false;
540 
541     Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
542     CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
543     // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
544     // which's size is 5 * sizeof(uint).
545     auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
546     if (!checkedSum.IsValid() ||
547         checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
548     {
549         context->validationError(GL_INVALID_OPERATION, kParamOverflow);
550         return false;
551     }
552 
553     return true;
554 }
555 
ValidateProgramUniform1i(const Context * context,ShaderProgramID program,UniformLocation location,GLint v0)556 bool ValidateProgramUniform1i(const Context *context,
557                               ShaderProgramID program,
558                               UniformLocation location,
559                               GLint v0)
560 {
561     return ValidateProgramUniform1iv(context, program, location, 1, &v0);
562 }
563 
ValidateProgramUniform2i(const Context * context,ShaderProgramID program,UniformLocation location,GLint v0,GLint v1)564 bool ValidateProgramUniform2i(const Context *context,
565                               ShaderProgramID program,
566                               UniformLocation location,
567                               GLint v0,
568                               GLint v1)
569 {
570     GLint xy[2] = {v0, v1};
571     return ValidateProgramUniform2iv(context, program, location, 1, xy);
572 }
573 
ValidateProgramUniform3i(const Context * context,ShaderProgramID program,UniformLocation location,GLint v0,GLint v1,GLint v2)574 bool ValidateProgramUniform3i(const Context *context,
575                               ShaderProgramID program,
576                               UniformLocation location,
577                               GLint v0,
578                               GLint v1,
579                               GLint v2)
580 {
581     GLint xyz[3] = {v0, v1, v2};
582     return ValidateProgramUniform3iv(context, program, location, 1, xyz);
583 }
584 
ValidateProgramUniform4i(const Context * context,ShaderProgramID program,UniformLocation location,GLint v0,GLint v1,GLint v2,GLint v3)585 bool ValidateProgramUniform4i(const Context *context,
586                               ShaderProgramID program,
587                               UniformLocation location,
588                               GLint v0,
589                               GLint v1,
590                               GLint v2,
591                               GLint v3)
592 {
593     GLint xyzw[4] = {v0, v1, v2, v3};
594     return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
595 }
596 
ValidateProgramUniform1ui(const Context * context,ShaderProgramID program,UniformLocation location,GLuint v0)597 bool ValidateProgramUniform1ui(const Context *context,
598                                ShaderProgramID program,
599                                UniformLocation location,
600                                GLuint v0)
601 {
602     return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
603 }
604 
ValidateProgramUniform2ui(const Context * context,ShaderProgramID program,UniformLocation location,GLuint v0,GLuint v1)605 bool ValidateProgramUniform2ui(const Context *context,
606                                ShaderProgramID program,
607                                UniformLocation location,
608                                GLuint v0,
609                                GLuint v1)
610 {
611     GLuint xy[2] = {v0, v1};
612     return ValidateProgramUniform2uiv(context, program, location, 1, xy);
613 }
614 
ValidateProgramUniform3ui(const Context * context,ShaderProgramID program,UniformLocation location,GLuint v0,GLuint v1,GLuint v2)615 bool ValidateProgramUniform3ui(const Context *context,
616                                ShaderProgramID program,
617                                UniformLocation location,
618                                GLuint v0,
619                                GLuint v1,
620                                GLuint v2)
621 {
622     GLuint xyz[3] = {v0, v1, v2};
623     return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
624 }
625 
ValidateProgramUniform4ui(const Context * context,ShaderProgramID program,UniformLocation location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)626 bool ValidateProgramUniform4ui(const Context *context,
627                                ShaderProgramID program,
628                                UniformLocation location,
629                                GLuint v0,
630                                GLuint v1,
631                                GLuint v2,
632                                GLuint v3)
633 {
634     GLuint xyzw[4] = {v0, v1, v2, v3};
635     return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
636 }
637 
ValidateProgramUniform1f(const Context * context,ShaderProgramID program,UniformLocation location,GLfloat v0)638 bool ValidateProgramUniform1f(const Context *context,
639                               ShaderProgramID program,
640                               UniformLocation location,
641                               GLfloat v0)
642 {
643     return ValidateProgramUniform1fv(context, program, location, 1, &v0);
644 }
645 
ValidateProgramUniform2f(const Context * context,ShaderProgramID program,UniformLocation location,GLfloat v0,GLfloat v1)646 bool ValidateProgramUniform2f(const Context *context,
647                               ShaderProgramID program,
648                               UniformLocation location,
649                               GLfloat v0,
650                               GLfloat v1)
651 {
652     GLfloat xy[2] = {v0, v1};
653     return ValidateProgramUniform2fv(context, program, location, 1, xy);
654 }
655 
ValidateProgramUniform3f(const Context * context,ShaderProgramID program,UniformLocation location,GLfloat v0,GLfloat v1,GLfloat v2)656 bool ValidateProgramUniform3f(const Context *context,
657                               ShaderProgramID program,
658                               UniformLocation location,
659                               GLfloat v0,
660                               GLfloat v1,
661                               GLfloat v2)
662 {
663     GLfloat xyz[3] = {v0, v1, v2};
664     return ValidateProgramUniform3fv(context, program, location, 1, xyz);
665 }
666 
ValidateProgramUniform4f(const Context * context,ShaderProgramID program,UniformLocation location,GLfloat v0,GLfloat v1,GLfloat v2,GLfloat v3)667 bool ValidateProgramUniform4f(const Context *context,
668                               ShaderProgramID program,
669                               UniformLocation location,
670                               GLfloat v0,
671                               GLfloat v1,
672                               GLfloat v2,
673                               GLfloat v3)
674 {
675     GLfloat xyzw[4] = {v0, v1, v2, v3};
676     return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
677 }
678 
ValidateProgramUniform1iv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLint * value)679 bool ValidateProgramUniform1iv(const Context *context,
680                                ShaderProgramID program,
681                                UniformLocation location,
682                                GLsizei count,
683                                const GLint *value)
684 {
685     // Check for ES31 program uniform entry points
686     if (context->getClientVersion() < Version(3, 1))
687     {
688         context->validationError(GL_INVALID_OPERATION, kES31Required);
689         return false;
690     }
691 
692     const LinkedUniform *uniform = nullptr;
693     Program *programObject       = GetValidProgram(context, program);
694     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
695            ValidateUniform1ivValue(context, uniform->type, count, value);
696 }
697 
ValidateProgramUniform2iv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLint * value)698 bool ValidateProgramUniform2iv(const Context *context,
699                                ShaderProgramID program,
700                                UniformLocation location,
701                                GLsizei count,
702                                const GLint *value)
703 {
704     return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
705 }
706 
ValidateProgramUniform3iv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLint * value)707 bool ValidateProgramUniform3iv(const Context *context,
708                                ShaderProgramID program,
709                                UniformLocation location,
710                                GLsizei count,
711                                const GLint *value)
712 {
713     return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
714 }
715 
ValidateProgramUniform4iv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLint * value)716 bool ValidateProgramUniform4iv(const Context *context,
717                                ShaderProgramID program,
718                                UniformLocation location,
719                                GLsizei count,
720                                const GLint *value)
721 {
722     return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
723 }
724 
ValidateProgramUniform1uiv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLuint * value)725 bool ValidateProgramUniform1uiv(const Context *context,
726                                 ShaderProgramID program,
727                                 UniformLocation location,
728                                 GLsizei count,
729                                 const GLuint *value)
730 {
731     return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
732 }
733 
ValidateProgramUniform2uiv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLuint * value)734 bool ValidateProgramUniform2uiv(const Context *context,
735                                 ShaderProgramID program,
736                                 UniformLocation location,
737                                 GLsizei count,
738                                 const GLuint *value)
739 {
740     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
741 }
742 
ValidateProgramUniform3uiv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLuint * value)743 bool ValidateProgramUniform3uiv(const Context *context,
744                                 ShaderProgramID program,
745                                 UniformLocation location,
746                                 GLsizei count,
747                                 const GLuint *value)
748 {
749     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
750 }
751 
ValidateProgramUniform4uiv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLuint * value)752 bool ValidateProgramUniform4uiv(const Context *context,
753                                 ShaderProgramID program,
754                                 UniformLocation location,
755                                 GLsizei count,
756                                 const GLuint *value)
757 {
758     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
759 }
760 
ValidateProgramUniform1fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLfloat * value)761 bool ValidateProgramUniform1fv(const Context *context,
762                                ShaderProgramID program,
763                                UniformLocation location,
764                                GLsizei count,
765                                const GLfloat *value)
766 {
767     return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
768 }
769 
ValidateProgramUniform2fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLfloat * value)770 bool ValidateProgramUniform2fv(const Context *context,
771                                ShaderProgramID program,
772                                UniformLocation location,
773                                GLsizei count,
774                                const GLfloat *value)
775 {
776     return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
777 }
778 
ValidateProgramUniform3fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLfloat * value)779 bool ValidateProgramUniform3fv(const Context *context,
780                                ShaderProgramID program,
781                                UniformLocation location,
782                                GLsizei count,
783                                const GLfloat *value)
784 {
785     return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
786 }
787 
ValidateProgramUniform4fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,const GLfloat * value)788 bool ValidateProgramUniform4fv(const Context *context,
789                                ShaderProgramID program,
790                                UniformLocation location,
791                                GLsizei count,
792                                const GLfloat *value)
793 {
794     return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
795 }
796 
ValidateProgramUniformMatrix2fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)797 bool ValidateProgramUniformMatrix2fv(const Context *context,
798                                      ShaderProgramID program,
799                                      UniformLocation location,
800                                      GLsizei count,
801                                      GLboolean transpose,
802                                      const GLfloat *value)
803 {
804     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
805                                         transpose);
806 }
807 
ValidateProgramUniformMatrix3fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)808 bool ValidateProgramUniformMatrix3fv(const Context *context,
809                                      ShaderProgramID program,
810                                      UniformLocation location,
811                                      GLsizei count,
812                                      GLboolean transpose,
813                                      const GLfloat *value)
814 {
815     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
816                                         transpose);
817 }
818 
ValidateProgramUniformMatrix4fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)819 bool ValidateProgramUniformMatrix4fv(const Context *context,
820                                      ShaderProgramID program,
821                                      UniformLocation location,
822                                      GLsizei count,
823                                      GLboolean transpose,
824                                      const GLfloat *value)
825 {
826     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
827                                         transpose);
828 }
829 
ValidateProgramUniformMatrix2x3fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)830 bool ValidateProgramUniformMatrix2x3fv(const Context *context,
831                                        ShaderProgramID program,
832                                        UniformLocation location,
833                                        GLsizei count,
834                                        GLboolean transpose,
835                                        const GLfloat *value)
836 {
837     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
838                                         transpose);
839 }
840 
ValidateProgramUniformMatrix3x2fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)841 bool ValidateProgramUniformMatrix3x2fv(const Context *context,
842                                        ShaderProgramID program,
843                                        UniformLocation location,
844                                        GLsizei count,
845                                        GLboolean transpose,
846                                        const GLfloat *value)
847 {
848     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
849                                         transpose);
850 }
851 
ValidateProgramUniformMatrix2x4fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)852 bool ValidateProgramUniformMatrix2x4fv(const Context *context,
853                                        ShaderProgramID program,
854                                        UniformLocation location,
855                                        GLsizei count,
856                                        GLboolean transpose,
857                                        const GLfloat *value)
858 {
859     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
860                                         transpose);
861 }
862 
ValidateProgramUniformMatrix4x2fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)863 bool ValidateProgramUniformMatrix4x2fv(const Context *context,
864                                        ShaderProgramID program,
865                                        UniformLocation location,
866                                        GLsizei count,
867                                        GLboolean transpose,
868                                        const GLfloat *value)
869 {
870     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
871                                         transpose);
872 }
873 
ValidateProgramUniformMatrix3x4fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)874 bool ValidateProgramUniformMatrix3x4fv(const Context *context,
875                                        ShaderProgramID program,
876                                        UniformLocation location,
877                                        GLsizei count,
878                                        GLboolean transpose,
879                                        const GLfloat *value)
880 {
881     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
882                                         transpose);
883 }
884 
ValidateProgramUniformMatrix4x3fv(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)885 bool ValidateProgramUniformMatrix4x3fv(const Context *context,
886                                        ShaderProgramID program,
887                                        UniformLocation location,
888                                        GLsizei count,
889                                        GLboolean transpose,
890                                        const GLfloat *value)
891 {
892     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
893                                         transpose);
894 }
895 
ValidateGetTexLevelParameterfv(const Context * context,TextureTarget target,GLint level,GLenum pname,const GLfloat * params)896 bool ValidateGetTexLevelParameterfv(const Context *context,
897                                     TextureTarget target,
898                                     GLint level,
899                                     GLenum pname,
900                                     const GLfloat *params)
901 {
902     if (context->getClientVersion() < ES_3_1)
903     {
904         context->validationError(GL_INVALID_OPERATION, kES31Required);
905         return false;
906     }
907 
908     return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
909 }
910 
ValidateGetTexLevelParameterfvRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)911 bool ValidateGetTexLevelParameterfvRobustANGLE(const Context *context,
912                                                TextureTarget target,
913                                                GLint level,
914                                                GLenum pname,
915                                                GLsizei bufSize,
916                                                const GLsizei *length,
917                                                const GLfloat *params)
918 {
919     UNIMPLEMENTED();
920     return false;
921 }
922 
ValidateGetTexLevelParameteriv(const Context * context,TextureTarget target,GLint level,GLenum pname,const GLint * params)923 bool ValidateGetTexLevelParameteriv(const Context *context,
924                                     TextureTarget target,
925                                     GLint level,
926                                     GLenum pname,
927                                     const GLint *params)
928 {
929     if (context->getClientVersion() < ES_3_1)
930     {
931         context->validationError(GL_INVALID_OPERATION, kES31Required);
932         return false;
933     }
934 
935     return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
936 }
937 
ValidateGetTexLevelParameterivRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)938 bool ValidateGetTexLevelParameterivRobustANGLE(const Context *context,
939                                                TextureTarget target,
940                                                GLint level,
941                                                GLenum pname,
942                                                GLsizei bufSize,
943                                                const GLsizei *length,
944                                                const GLint *params)
945 {
946     UNIMPLEMENTED();
947     return false;
948 }
949 
ValidateTexStorage2DMultisample(const Context * context,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)950 bool ValidateTexStorage2DMultisample(const Context *context,
951                                      TextureType target,
952                                      GLsizei samples,
953                                      GLenum internalFormat,
954                                      GLsizei width,
955                                      GLsizei height,
956                                      GLboolean fixedSampleLocations)
957 {
958     if (context->getClientVersion() < ES_3_1)
959     {
960         context->validationError(GL_INVALID_OPERATION, kES31Required);
961         return false;
962     }
963 
964     return ValidateTexStorage2DMultisampleBase(context, target, samples, internalFormat, width,
965                                                height);
966 }
967 
ValidateTexStorageMem2DMultisampleEXT(const Context * context,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations,MemoryObjectID memory,GLuint64 offset)968 bool ValidateTexStorageMem2DMultisampleEXT(const Context *context,
969                                            TextureType target,
970                                            GLsizei samples,
971                                            GLenum internalFormat,
972                                            GLsizei width,
973                                            GLsizei height,
974                                            GLboolean fixedSampleLocations,
975                                            MemoryObjectID memory,
976                                            GLuint64 offset)
977 {
978     if (!context->getExtensions().memoryObject)
979     {
980         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
981         return false;
982     }
983 
984     UNIMPLEMENTED();
985     return false;
986 }
987 
ValidateGetMultisamplefv(const Context * context,GLenum pname,GLuint index,const GLfloat * val)988 bool ValidateGetMultisamplefv(const Context *context,
989                               GLenum pname,
990                               GLuint index,
991                               const GLfloat *val)
992 {
993     if (context->getClientVersion() < ES_3_1)
994     {
995         context->validationError(GL_INVALID_OPERATION, kES31Required);
996         return false;
997     }
998 
999     return ValidateGetMultisamplefvBase(context, pname, index, val);
1000 }
1001 
ValidateGetMultisamplefvRobustANGLE(const Context * context,GLenum pname,GLuint index,GLsizei bufSize,const GLsizei * length,const GLfloat * val)1002 bool ValidateGetMultisamplefvRobustANGLE(const Context *context,
1003                                          GLenum pname,
1004                                          GLuint index,
1005                                          GLsizei bufSize,
1006                                          const GLsizei *length,
1007                                          const GLfloat *val)
1008 {
1009     UNIMPLEMENTED();
1010     return false;
1011 }
1012 
ValidateFramebufferParameteri(const Context * context,GLenum target,GLenum pname,GLint param)1013 bool ValidateFramebufferParameteri(const Context *context, GLenum target, GLenum pname, GLint param)
1014 {
1015     if (context->getClientVersion() < ES_3_1)
1016     {
1017         context->validationError(GL_INVALID_OPERATION, kES31Required);
1018         return false;
1019     }
1020 
1021     if (!ValidFramebufferTarget(context, target))
1022     {
1023         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1024         return false;
1025     }
1026 
1027     switch (pname)
1028     {
1029         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1030         {
1031             GLint maxWidth = context->getCaps().maxFramebufferWidth;
1032             if (param < 0 || param > maxWidth)
1033             {
1034                 context->validationError(GL_INVALID_VALUE, kExceedsFramebufferWidth);
1035                 return false;
1036             }
1037             break;
1038         }
1039         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1040         {
1041             GLint maxHeight = context->getCaps().maxFramebufferHeight;
1042             if (param < 0 || param > maxHeight)
1043             {
1044                 context->validationError(GL_INVALID_VALUE, kExceedsFramebufferHeight);
1045                 return false;
1046             }
1047             break;
1048         }
1049         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1050         {
1051             GLint maxSamples = context->getCaps().maxFramebufferSamples;
1052             if (param < 0 || param > maxSamples)
1053             {
1054                 context->validationError(GL_INVALID_VALUE, kExceedsFramebufferSamples);
1055                 return false;
1056             }
1057             break;
1058         }
1059         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1060         {
1061             break;
1062         }
1063         case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1064         {
1065             if (!context->getExtensions().geometryShader)
1066             {
1067                 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
1068                 return false;
1069             }
1070             GLint maxLayers = context->getCaps().maxFramebufferLayers;
1071             if (param < 0 || param > maxLayers)
1072             {
1073                 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferLayer);
1074                 return false;
1075             }
1076             break;
1077         }
1078         default:
1079         {
1080             context->validationError(GL_INVALID_ENUM, kInvalidPname);
1081             return false;
1082         }
1083     }
1084 
1085     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1086     ASSERT(framebuffer);
1087     if (framebuffer->isDefault())
1088     {
1089         context->validationError(GL_INVALID_OPERATION, kDefaultFramebuffer);
1090         return false;
1091     }
1092     return true;
1093 }
1094 
ValidateGetFramebufferParameteriv(const Context * context,GLenum target,GLenum pname,const GLint * params)1095 bool ValidateGetFramebufferParameteriv(const Context *context,
1096                                        GLenum target,
1097                                        GLenum pname,
1098                                        const GLint *params)
1099 {
1100     if (context->getClientVersion() < ES_3_1)
1101     {
1102         context->validationError(GL_INVALID_OPERATION, kES31Required);
1103         return false;
1104     }
1105 
1106     if (!ValidFramebufferTarget(context, target))
1107     {
1108         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1109         return false;
1110     }
1111 
1112     switch (pname)
1113     {
1114         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1115         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1116         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1117         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1118             break;
1119         case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1120             if (!context->getExtensions().geometryShader)
1121             {
1122                 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
1123                 return false;
1124             }
1125             break;
1126         default:
1127             context->validationError(GL_INVALID_ENUM, kInvalidPname);
1128             return false;
1129     }
1130 
1131     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1132     ASSERT(framebuffer);
1133 
1134     if (framebuffer->isDefault())
1135     {
1136         context->validationError(GL_INVALID_OPERATION, kDefaultFramebuffer);
1137         return false;
1138     }
1139     return true;
1140 }
1141 
ValidateGetFramebufferParameterivRobustANGLE(const Context * context,GLenum target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)1142 bool ValidateGetFramebufferParameterivRobustANGLE(const Context *context,
1143                                                   GLenum target,
1144                                                   GLenum pname,
1145                                                   GLsizei bufSize,
1146                                                   const GLsizei *length,
1147                                                   const GLint *params)
1148 {
1149     UNIMPLEMENTED();
1150     return false;
1151 }
1152 
ValidateGetProgramResourceIndex(const Context * context,ShaderProgramID program,GLenum programInterface,const GLchar * name)1153 bool ValidateGetProgramResourceIndex(const Context *context,
1154                                      ShaderProgramID program,
1155                                      GLenum programInterface,
1156                                      const GLchar *name)
1157 {
1158     if (context->getClientVersion() < ES_3_1)
1159     {
1160         context->validationError(GL_INVALID_OPERATION, kES31Required);
1161         return false;
1162     }
1163 
1164     Program *programObject = GetValidProgram(context, program);
1165     if (programObject == nullptr)
1166     {
1167         return false;
1168     }
1169 
1170     if (!ValidateNamedProgramInterface(programInterface))
1171     {
1172         context->validationError(GL_INVALID_ENUM, kInvalidProgramInterface);
1173         return false;
1174     }
1175 
1176     return true;
1177 }
1178 
ValidateBindVertexBuffer(const Context * context,GLuint bindingIndex,BufferID buffer,GLintptr offset,GLsizei stride)1179 bool ValidateBindVertexBuffer(const Context *context,
1180                               GLuint bindingIndex,
1181                               BufferID buffer,
1182                               GLintptr offset,
1183                               GLsizei stride)
1184 {
1185     if (context->getClientVersion() < ES_3_1)
1186     {
1187         context->validationError(GL_INVALID_OPERATION, kES31Required);
1188         return false;
1189     }
1190 
1191     if (!context->isBufferGenerated(buffer))
1192     {
1193         context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
1194         return false;
1195     }
1196 
1197     const Caps &caps = context->getCaps();
1198     if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
1199     {
1200         context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
1201         return false;
1202     }
1203 
1204     if (offset < 0)
1205     {
1206         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
1207         return false;
1208     }
1209 
1210     if (stride < 0 || stride > caps.maxVertexAttribStride)
1211     {
1212         context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
1213         return false;
1214     }
1215 
1216     // [OpenGL ES 3.1] Section 10.3.1 page 244:
1217     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1218     if (context->getState().getVertexArrayId().value == 0)
1219     {
1220         context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
1221         return false;
1222     }
1223 
1224     return true;
1225 }
1226 
ValidateVertexBindingDivisor(const Context * context,GLuint bindingIndex,GLuint divisor)1227 bool ValidateVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor)
1228 {
1229     if (context->getClientVersion() < ES_3_1)
1230     {
1231         context->validationError(GL_INVALID_OPERATION, kES31Required);
1232         return false;
1233     }
1234 
1235     const Caps &caps = context->getCaps();
1236     if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
1237     {
1238         context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
1239         return false;
1240     }
1241 
1242     // [OpenGL ES 3.1] Section 10.3.1 page 243:
1243     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1244     if (context->getState().getVertexArrayId().value == 0)
1245     {
1246         context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
1247         return false;
1248     }
1249 
1250     return true;
1251 }
1252 
ValidateVertexAttribFormat(const Context * context,GLuint attribindex,GLint size,VertexAttribType type,GLboolean normalized,GLuint relativeoffset)1253 bool ValidateVertexAttribFormat(const Context *context,
1254                                 GLuint attribindex,
1255                                 GLint size,
1256                                 VertexAttribType type,
1257                                 GLboolean normalized,
1258                                 GLuint relativeoffset)
1259 {
1260     if (!ValidateVertexAttribFormatCommon(context, relativeoffset))
1261     {
1262         return false;
1263     }
1264 
1265     return ValidateFloatVertexFormat(context, attribindex, size, type);
1266 }
1267 
ValidateVertexAttribIFormat(const Context * context,GLuint attribindex,GLint size,VertexAttribType type,GLuint relativeoffset)1268 bool ValidateVertexAttribIFormat(const Context *context,
1269                                  GLuint attribindex,
1270                                  GLint size,
1271                                  VertexAttribType type,
1272                                  GLuint relativeoffset)
1273 {
1274     if (!ValidateVertexAttribFormatCommon(context, relativeoffset))
1275     {
1276         return false;
1277     }
1278 
1279     return ValidateIntegerVertexFormat(context, attribindex, size, type);
1280 }
1281 
ValidateVertexAttribBinding(const Context * context,GLuint attribIndex,GLuint bindingIndex)1282 bool ValidateVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
1283 {
1284     if (context->getClientVersion() < ES_3_1)
1285     {
1286         context->validationError(GL_INVALID_OPERATION, kES31Required);
1287         return false;
1288     }
1289 
1290     // [OpenGL ES 3.1] Section 10.3.1 page 243:
1291     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1292     if (context->getState().getVertexArrayId().value == 0)
1293     {
1294         context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
1295         return false;
1296     }
1297 
1298     const Caps &caps = context->getCaps();
1299     if (attribIndex >= static_cast<GLuint>(caps.maxVertexAttributes))
1300     {
1301         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
1302         return false;
1303     }
1304 
1305     if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
1306     {
1307         context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
1308         return false;
1309     }
1310 
1311     return true;
1312 }
1313 
ValidateGetProgramResourceName(const Context * context,ShaderProgramID program,GLenum programInterface,GLuint index,GLsizei bufSize,const GLsizei * length,const GLchar * name)1314 bool ValidateGetProgramResourceName(const Context *context,
1315                                     ShaderProgramID program,
1316                                     GLenum programInterface,
1317                                     GLuint index,
1318                                     GLsizei bufSize,
1319                                     const GLsizei *length,
1320                                     const GLchar *name)
1321 {
1322     if (context->getClientVersion() < ES_3_1)
1323     {
1324         context->validationError(GL_INVALID_OPERATION, kES31Required);
1325         return false;
1326     }
1327 
1328     Program *programObject = GetValidProgram(context, program);
1329     if (programObject == nullptr)
1330     {
1331         return false;
1332     }
1333 
1334     if (!ValidateNamedProgramInterface(programInterface))
1335     {
1336         context->validationError(GL_INVALID_ENUM, kInvalidProgramInterface);
1337         return false;
1338     }
1339 
1340     if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1341     {
1342         context->validationError(GL_INVALID_VALUE, kInvalidProgramResourceIndex);
1343         return false;
1344     }
1345 
1346     if (bufSize < 0)
1347     {
1348         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
1349         return false;
1350     }
1351 
1352     return true;
1353 }
1354 
ValidateDispatchCompute(const Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)1355 bool ValidateDispatchCompute(const Context *context,
1356                              GLuint numGroupsX,
1357                              GLuint numGroupsY,
1358                              GLuint numGroupsZ)
1359 {
1360     if (context->getClientVersion() < ES_3_1)
1361     {
1362         context->validationError(GL_INVALID_OPERATION, kES31Required);
1363         return false;
1364     }
1365 
1366     const State &state                  = context->getState();
1367     const ProgramExecutable *executable = state.getProgramExecutable();
1368 
1369     if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
1370     {
1371         context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
1372         return false;
1373     }
1374 
1375     const Caps &caps = context->getCaps();
1376     if (numGroupsX > static_cast<GLuint>(caps.maxComputeWorkGroupCount[0]))
1377     {
1378         context->validationError(GL_INVALID_VALUE, kExceedsComputeWorkGroupCountX);
1379         return false;
1380     }
1381     if (numGroupsY > static_cast<GLuint>(caps.maxComputeWorkGroupCount[1]))
1382     {
1383         context->validationError(GL_INVALID_VALUE, kExceedsComputeWorkGroupCountY);
1384         return false;
1385     }
1386     if (numGroupsZ > static_cast<GLuint>(caps.maxComputeWorkGroupCount[2]))
1387     {
1388         context->validationError(GL_INVALID_VALUE, kExceedsComputeWorkGroupCountZ);
1389         return false;
1390     }
1391 
1392     return true;
1393 }
1394 
ValidateDispatchComputeIndirect(const Context * context,GLintptr indirect)1395 bool ValidateDispatchComputeIndirect(const Context *context, GLintptr indirect)
1396 {
1397     if (context->getClientVersion() < ES_3_1)
1398     {
1399         context->validationError(GL_INVALID_OPERATION, kES31Required);
1400         return false;
1401     }
1402 
1403     const State &state                  = context->getState();
1404     const ProgramExecutable *executable = state.getProgramExecutable();
1405 
1406     if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
1407     {
1408         context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
1409         return false;
1410     }
1411 
1412     if (indirect < 0)
1413     {
1414         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
1415         return false;
1416     }
1417 
1418     if ((indirect & (sizeof(GLuint) - 1)) != 0)
1419     {
1420         context->validationError(GL_INVALID_VALUE, kOffsetMustBeMultipleOfUint);
1421         return false;
1422     }
1423 
1424     Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
1425     if (!dispatchIndirectBuffer)
1426     {
1427         context->validationError(GL_INVALID_OPERATION, kDispatchIndirectBufferNotBound);
1428         return false;
1429     }
1430 
1431     CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
1432     auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
1433     if (!checkedSum.IsValid() ||
1434         checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
1435     {
1436         context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
1437         return false;
1438     }
1439 
1440     return true;
1441 }
1442 
ValidateBindImageTexture(const Context * context,GLuint unit,TextureID texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)1443 bool ValidateBindImageTexture(const Context *context,
1444                               GLuint unit,
1445                               TextureID texture,
1446                               GLint level,
1447                               GLboolean layered,
1448                               GLint layer,
1449                               GLenum access,
1450                               GLenum format)
1451 {
1452     if (context->getClientVersion() < ES_3_1)
1453     {
1454         context->validationError(GL_INVALID_OPERATION, kES31Required);
1455         return false;
1456     }
1457 
1458     GLuint maxImageUnits = static_cast<GLuint>(context->getCaps().maxImageUnits);
1459     if (unit >= maxImageUnits)
1460     {
1461         context->validationError(GL_INVALID_VALUE, kExceedsMaxImageUnits);
1462         return false;
1463     }
1464 
1465     if (level < 0)
1466     {
1467         context->validationError(GL_INVALID_VALUE, kNegativeLevel);
1468         return false;
1469     }
1470 
1471     if (layer < 0)
1472     {
1473         context->validationError(GL_INVALID_VALUE, kNegativeLayer);
1474         return false;
1475     }
1476 
1477     if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1478     {
1479         context->validationError(GL_INVALID_ENUM, kInvalidImageAccess);
1480         return false;
1481     }
1482 
1483     switch (format)
1484     {
1485         case GL_RGBA32F:
1486         case GL_RGBA16F:
1487         case GL_R32F:
1488         case GL_RGBA32UI:
1489         case GL_RGBA16UI:
1490         case GL_RGBA8UI:
1491         case GL_R32UI:
1492         case GL_RGBA32I:
1493         case GL_RGBA16I:
1494         case GL_RGBA8I:
1495         case GL_R32I:
1496         case GL_RGBA8:
1497         case GL_RGBA8_SNORM:
1498             break;
1499         default:
1500             context->validationError(GL_INVALID_VALUE, kInvalidImageFormat);
1501             return false;
1502     }
1503 
1504     if (texture.value != 0)
1505     {
1506         Texture *tex = context->getTexture(texture);
1507 
1508         if (tex == nullptr)
1509         {
1510             context->validationError(GL_INVALID_VALUE, kMissingTextureName);
1511             return false;
1512         }
1513 
1514         if (!tex->getImmutableFormat())
1515         {
1516             context->validationError(GL_INVALID_OPERATION, kTextureIsNotImmutable);
1517             return false;
1518         }
1519     }
1520 
1521     return true;
1522 }
1523 
ValidateGetProgramResourceLocation(const Context * context,ShaderProgramID program,GLenum programInterface,const GLchar * name)1524 bool ValidateGetProgramResourceLocation(const Context *context,
1525                                         ShaderProgramID program,
1526                                         GLenum programInterface,
1527                                         const GLchar *name)
1528 {
1529     if (context->getClientVersion() < ES_3_1)
1530     {
1531         context->validationError(GL_INVALID_OPERATION, kES31Required);
1532         return false;
1533     }
1534 
1535     Program *programObject = GetValidProgram(context, program);
1536     if (programObject == nullptr)
1537     {
1538         return false;
1539     }
1540 
1541     if (!programObject->isLinked())
1542     {
1543         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
1544         return false;
1545     }
1546 
1547     if (!ValidateLocationProgramInterface(programInterface))
1548     {
1549         context->validationError(GL_INVALID_ENUM, kInvalidProgramInterface);
1550         return false;
1551     }
1552     return true;
1553 }
1554 
ValidateGetProgramResourceiv(const Context * context,ShaderProgramID program,GLenum programInterface,GLuint index,GLsizei propCount,const GLenum * props,GLsizei bufSize,const GLsizei * length,const GLint * params)1555 bool ValidateGetProgramResourceiv(const Context *context,
1556                                   ShaderProgramID program,
1557                                   GLenum programInterface,
1558                                   GLuint index,
1559                                   GLsizei propCount,
1560                                   const GLenum *props,
1561                                   GLsizei bufSize,
1562                                   const GLsizei *length,
1563                                   const GLint *params)
1564 {
1565     if (context->getClientVersion() < ES_3_1)
1566     {
1567         context->validationError(GL_INVALID_OPERATION, kES31Required);
1568         return false;
1569     }
1570 
1571     Program *programObject = GetValidProgram(context, program);
1572     if (programObject == nullptr)
1573     {
1574         return false;
1575     }
1576     if (!ValidateProgramInterface(programInterface))
1577     {
1578         context->validationError(GL_INVALID_ENUM, kInvalidProgramInterface);
1579         return false;
1580     }
1581     if (propCount <= 0)
1582     {
1583         context->validationError(GL_INVALID_VALUE, kInvalidPropCount);
1584         return false;
1585     }
1586     if (bufSize < 0)
1587     {
1588         context->validationError(GL_INVALID_VALUE, kNegativeBufSize);
1589         return false;
1590     }
1591     if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1592     {
1593         context->validationError(GL_INVALID_VALUE, kInvalidProgramResourceIndex);
1594         return false;
1595     }
1596     for (GLsizei i = 0; i < propCount; i++)
1597     {
1598         if (!ValidateProgramResourceProperty(context, props[i]))
1599         {
1600             context->validationError(GL_INVALID_ENUM, kInvalidProgramResourceProperty);
1601             return false;
1602         }
1603         if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1604         {
1605             context->validationError(GL_INVALID_OPERATION, kInvalidPropertyForProgramInterface);
1606             return false;
1607         }
1608     }
1609     return true;
1610 }
1611 
ValidateGetProgramInterfaceiv(const Context * context,ShaderProgramID program,GLenum programInterface,GLenum pname,const GLint * params)1612 bool ValidateGetProgramInterfaceiv(const Context *context,
1613                                    ShaderProgramID program,
1614                                    GLenum programInterface,
1615                                    GLenum pname,
1616                                    const GLint *params)
1617 {
1618     if (context->getClientVersion() < ES_3_1)
1619     {
1620         context->validationError(GL_INVALID_OPERATION, kES31Required);
1621         return false;
1622     }
1623 
1624     Program *programObject = GetValidProgram(context, program);
1625     if (programObject == nullptr)
1626     {
1627         return false;
1628     }
1629 
1630     if (!ValidateProgramInterface(programInterface))
1631     {
1632         context->validationError(GL_INVALID_ENUM, kInvalidProgramInterface);
1633         return false;
1634     }
1635 
1636     switch (pname)
1637     {
1638         case GL_ACTIVE_RESOURCES:
1639         case GL_MAX_NAME_LENGTH:
1640         case GL_MAX_NUM_ACTIVE_VARIABLES:
1641             break;
1642 
1643         default:
1644             context->validationError(GL_INVALID_ENUM, kInvalidPname);
1645             return false;
1646     }
1647 
1648     if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1649     {
1650         context->validationError(GL_INVALID_OPERATION, kAtomicCounterResourceName);
1651         return false;
1652     }
1653 
1654     if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1655     {
1656         switch (programInterface)
1657         {
1658             case GL_ATOMIC_COUNTER_BUFFER:
1659             case GL_SHADER_STORAGE_BLOCK:
1660             case GL_UNIFORM_BLOCK:
1661                 break;
1662 
1663             default:
1664                 context->validationError(GL_INVALID_OPERATION, kMaxActiveVariablesInterface);
1665                 return false;
1666         }
1667     }
1668 
1669     return true;
1670 }
1671 
ValidateGetProgramInterfaceivRobustANGLE(const Context * context,ShaderProgramID program,GLenum programInterface,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)1672 bool ValidateGetProgramInterfaceivRobustANGLE(const Context *context,
1673                                               ShaderProgramID program,
1674                                               GLenum programInterface,
1675                                               GLenum pname,
1676                                               GLsizei bufSize,
1677                                               const GLsizei *length,
1678                                               const GLint *params)
1679 {
1680     UNIMPLEMENTED();
1681     return false;
1682 }
1683 
ValidateGenOrDeleteES31(const Context * context,GLint n)1684 static bool ValidateGenOrDeleteES31(const Context *context, GLint n)
1685 {
1686     if (context->getClientVersion() < ES_3_1)
1687     {
1688         context->validationError(GL_INVALID_OPERATION, kES31Required);
1689         return false;
1690     }
1691 
1692     return ValidateGenOrDelete(context, n);
1693 }
1694 
ValidateGenProgramPipelines(const Context * context,GLsizei n,const ProgramPipelineID * pipelines)1695 bool ValidateGenProgramPipelines(const Context *context,
1696                                  GLsizei n,
1697                                  const ProgramPipelineID *pipelines)
1698 {
1699     return ValidateGenOrDeleteES31(context, n);
1700 }
1701 
ValidateDeleteProgramPipelines(const Context * context,GLsizei n,const ProgramPipelineID * pipelines)1702 bool ValidateDeleteProgramPipelines(const Context *context,
1703                                     GLsizei n,
1704                                     const ProgramPipelineID *pipelines)
1705 {
1706     return ValidateGenOrDeleteES31(context, n);
1707 }
1708 
ValidateBindProgramPipeline(const Context * context,ProgramPipelineID pipeline)1709 bool ValidateBindProgramPipeline(const Context *context, ProgramPipelineID pipeline)
1710 {
1711     if (context->getClientVersion() < ES_3_1)
1712     {
1713         context->validationError(GL_INVALID_OPERATION, kES31Required);
1714         return false;
1715     }
1716 
1717     if (!context->isProgramPipelineGenerated({pipeline}))
1718     {
1719         context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
1720         return false;
1721     }
1722 
1723     return true;
1724 }
1725 
ValidateIsProgramPipeline(const Context * context,ProgramPipelineID pipeline)1726 bool ValidateIsProgramPipeline(const Context *context, ProgramPipelineID pipeline)
1727 {
1728     if (context->getClientVersion() < ES_3_1)
1729     {
1730         context->validationError(GL_INVALID_OPERATION, kES31Required);
1731         return false;
1732     }
1733 
1734     return true;
1735 }
1736 
ValidateUseProgramStages(const Context * context,ProgramPipelineID pipeline,GLbitfield stages,ShaderProgramID programId)1737 bool ValidateUseProgramStages(const Context *context,
1738                               ProgramPipelineID pipeline,
1739                               GLbitfield stages,
1740                               ShaderProgramID programId)
1741 {
1742     if (context->getClientVersion() < ES_3_1)
1743     {
1744         context->validationError(GL_INVALID_OPERATION, kES31Required);
1745         return false;
1746     }
1747 
1748     // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is
1749     // not the reserved value GL_ALL_SHADER_BITS.
1750     const GLbitfield knownShaderBits =
1751         GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
1752     if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS))
1753     {
1754         context->validationError(GL_INVALID_VALUE, kUnrecognizedShaderStageBit);
1755         return false;
1756     }
1757 
1758     // GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call
1759     // to glGenProgramPipelines or if such a name has been deleted by a call to
1760     // glDeleteProgramPipelines.
1761     if (!context->isProgramPipelineGenerated({pipeline}))
1762     {
1763         context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
1764         return false;
1765     }
1766 
1767     // If program is zero, or refers to a program object with no valid shader executable for a given
1768     // stage, it is as if the pipeline object has no programmable stage configured for the indicated
1769     // shader stages.
1770     if (programId.value == 0)
1771     {
1772         return true;
1773     }
1774 
1775     Program *program = context->getProgramNoResolveLink(programId);
1776     if (!program)
1777     {
1778         context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
1779         return false;
1780     }
1781 
1782     // GL_INVALID_OPERATION is generated if program refers to a program object that was not linked
1783     // with its GL_PROGRAM_SEPARABLE status set.
1784     // resolveLink() may not have been called if glCreateShaderProgramv() was not used and
1785     // glDetachShader() was not called.
1786     program->resolveLink(context);
1787     if (!program->isSeparable())
1788     {
1789         context->validationError(GL_INVALID_OPERATION, kProgramNotSeparable);
1790         return false;
1791     }
1792 
1793     // GL_INVALID_OPERATION is generated if program refers to a program object that has not been
1794     // successfully linked.
1795     if (!program->isLinked())
1796     {
1797         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
1798         return false;
1799     }
1800 
1801     return true;
1802 }
1803 
ValidateActiveShaderProgram(const Context * context,ProgramPipelineID pipeline,ShaderProgramID programId)1804 bool ValidateActiveShaderProgram(const Context *context,
1805                                  ProgramPipelineID pipeline,
1806                                  ShaderProgramID programId)
1807 {
1808     // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
1809     // call to GenProgramPipelines or if such a name has since been deleted by
1810     // DeleteProgramPipelines.
1811     if (!context->isProgramPipelineGenerated({pipeline}))
1812     {
1813         context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
1814         return false;
1815     }
1816 
1817     // An INVALID_VALUE error is generated if program is not zero and is not the name of either a
1818     // program or shader object.
1819     if ((programId.value != 0) && !context->isProgram(programId) && !context->isShader(programId))
1820     {
1821         context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
1822         return false;
1823     }
1824 
1825     // An INVALID_OPERATION error is generated if program is the name of a shader object.
1826     if (context->isShader(programId))
1827     {
1828         context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
1829         return false;
1830     }
1831 
1832     // An INVALID_OPERATION error is generated if program is not zero and has not been linked, or
1833     // was last linked unsuccessfully. The active program is not modified.
1834     Program *program = context->getProgramNoResolveLink(programId);
1835     if ((programId.value != 0) && !program->isLinked())
1836     {
1837         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
1838         return false;
1839     }
1840 
1841     return true;
1842 }
1843 
ValidateCreateShaderProgramv(const Context * context,ShaderType type,GLsizei count,const GLchar * const * strings)1844 bool ValidateCreateShaderProgramv(const Context *context,
1845                                   ShaderType type,
1846                                   GLsizei count,
1847                                   const GLchar *const *strings)
1848 {
1849     if (context->getClientVersion() < ES_3_1)
1850     {
1851         context->validationError(GL_INVALID_OPERATION, kES31Required);
1852         return false;
1853     }
1854 
1855     // GL_INVALID_ENUM is generated if type is not an accepted shader type.
1856     if ((type != ShaderType::Vertex) && (type != ShaderType::Fragment) &&
1857         (type != ShaderType::Compute))
1858     {
1859         context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
1860         return false;
1861     }
1862 
1863     // GL_INVALID_VALUE is generated if count is negative.
1864     if (count < 0)
1865     {
1866         context->validationError(GL_INVALID_VALUE, kNegativeCount);
1867         return false;
1868     }
1869 
1870     return true;
1871 }
1872 
ValidateGetProgramPipelineiv(const Context * context,ProgramPipelineID pipeline,GLenum pname,const GLint * params)1873 bool ValidateGetProgramPipelineiv(const Context *context,
1874                                   ProgramPipelineID pipeline,
1875                                   GLenum pname,
1876                                   const GLint *params)
1877 {
1878     // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
1879     // call to GenProgramPipelines or if such a name has since been deleted by
1880     // DeleteProgramPipelines.
1881     if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated(pipeline)))
1882     {
1883         context->validationError(GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
1884         return false;
1885     }
1886 
1887     // An INVALID_ENUM error is generated if pname is not ACTIVE_PROGRAM,
1888     // INFO_LOG_LENGTH, VALIDATE_STATUS, or one of the type arguments in
1889     // table 7.1.
1890     switch (pname)
1891     {
1892         case GL_ACTIVE_PROGRAM:
1893         case GL_INFO_LOG_LENGTH:
1894         case GL_VALIDATE_STATUS:
1895         case GL_VERTEX_SHADER:
1896         case GL_FRAGMENT_SHADER:
1897         case GL_COMPUTE_SHADER:
1898             break;
1899 
1900         default:
1901             context->validationError(GL_INVALID_ENUM, kInvalidPname);
1902             return false;
1903     }
1904 
1905     return true;
1906 }
1907 
ValidateValidateProgramPipeline(const Context * context,ProgramPipelineID pipeline)1908 bool ValidateValidateProgramPipeline(const Context *context, ProgramPipelineID pipeline)
1909 {
1910     if (pipeline.value == 0)
1911     {
1912         return false;
1913     }
1914 
1915     if (!context->isProgramPipelineGenerated(pipeline))
1916     {
1917         context->validationError(GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
1918         return false;
1919     }
1920 
1921     return true;
1922 }
1923 
ValidateGetProgramPipelineInfoLog(const Context * context,ProgramPipelineID pipeline,GLsizei bufSize,const GLsizei * length,const GLchar * infoLog)1924 bool ValidateGetProgramPipelineInfoLog(const Context *context,
1925                                        ProgramPipelineID pipeline,
1926                                        GLsizei bufSize,
1927                                        const GLsizei *length,
1928                                        const GLchar *infoLog)
1929 {
1930     if (bufSize < 0)
1931     {
1932         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
1933         return false;
1934     }
1935 
1936     if (!context->isProgramPipelineGenerated(pipeline))
1937     {
1938         context->validationError(GL_INVALID_VALUE, kProgramPipelineDoesNotExist);
1939         return false;
1940     }
1941 
1942     return true;
1943 }
1944 
ValidateMemoryBarrier(const Context * context,GLbitfield barriers)1945 bool ValidateMemoryBarrier(const Context *context, GLbitfield barriers)
1946 {
1947     if (context->getClientVersion() < ES_3_1)
1948     {
1949         context->validationError(GL_INVALID_OPERATION, kES31Required);
1950         return false;
1951     }
1952 
1953     if (barriers == GL_ALL_BARRIER_BITS)
1954     {
1955         return true;
1956     }
1957 
1958     GLbitfield supported_barrier_bits =
1959         GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1960         GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1961         GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1962         GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
1963         GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
1964 
1965     if (context->getExtensions().bufferStorageEXT)
1966     {
1967         supported_barrier_bits |= GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
1968     }
1969 
1970     if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
1971     {
1972         context->validationError(GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
1973         return false;
1974     }
1975 
1976     return true;
1977 }
1978 
ValidateMemoryBarrierByRegion(const Context * context,GLbitfield barriers)1979 bool ValidateMemoryBarrierByRegion(const Context *context, GLbitfield barriers)
1980 {
1981     if (context->getClientVersion() < ES_3_1)
1982     {
1983         context->validationError(GL_INVALID_OPERATION, kES31Required);
1984         return false;
1985     }
1986 
1987     if (barriers == GL_ALL_BARRIER_BITS)
1988     {
1989         return true;
1990     }
1991 
1992     GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1993                                         GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
1994                                         GL_SHADER_STORAGE_BARRIER_BIT |
1995                                         GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
1996     if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
1997     {
1998         context->validationError(GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
1999         return false;
2000     }
2001 
2002     return true;
2003 }
2004 
ValidateSampleMaski(const Context * context,GLuint maskNumber,GLbitfield mask)2005 bool ValidateSampleMaski(const Context *context, GLuint maskNumber, GLbitfield mask)
2006 {
2007     if (context->getClientVersion() < ES_3_1)
2008     {
2009         context->validationError(GL_INVALID_OPERATION, kES31Required);
2010         return false;
2011     }
2012 
2013     return ValidateSampleMaskiBase(context, maskNumber, mask);
2014 }
2015 
ValidateMinSampleShadingOES(const Context * context,GLfloat value)2016 bool ValidateMinSampleShadingOES(const Context *context, GLfloat value)
2017 {
2018     if (!context->getExtensions().sampleShadingOES)
2019     {
2020         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2021         return false;
2022     }
2023 
2024     return true;
2025 }
2026 
ValidateFramebufferTextureEXT(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level)2027 bool ValidateFramebufferTextureEXT(const Context *context,
2028                                    GLenum target,
2029                                    GLenum attachment,
2030                                    TextureID texture,
2031                                    GLint level)
2032 {
2033     if (!context->getExtensions().geometryShader)
2034     {
2035         context->validationError(GL_INVALID_OPERATION, kGeometryShaderExtensionNotEnabled);
2036         return false;
2037     }
2038 
2039     if (texture.value != 0)
2040     {
2041         Texture *tex = context->getTexture(texture);
2042 
2043         // [EXT_geometry_shader] Section 9.2.8 "Attaching Texture Images to a Framebuffer"
2044         // An INVALID_VALUE error is generated if <texture> is not the name of a texture object.
2045         // We put this validation before ValidateFramebufferTextureBase because it is an
2046         // INVALID_OPERATION error for both FramebufferTexture2D and FramebufferTextureLayer:
2047         // [OpenGL ES 3.1] Chapter 9.2.8 (FramebufferTexture2D)
2048         // An INVALID_OPERATION error is generated if texture is not zero, and does not name an
2049         // existing texture object of type matching textarget.
2050         // [OpenGL ES 3.1 Chapter 9.2.8 (FramebufferTextureLayer)
2051         // An INVALID_OPERATION error is generated if texture is non-zero and is not the name of a
2052         // three-dimensional or two-dimensional array texture.
2053         if (tex == nullptr)
2054         {
2055             context->validationError(GL_INVALID_VALUE, kInvalidTextureName);
2056             return false;
2057         }
2058 
2059         if (!ValidMipLevel(context, tex->getType(), level))
2060         {
2061             context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
2062             return false;
2063         }
2064     }
2065 
2066     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
2067     {
2068         return false;
2069     }
2070 
2071     return true;
2072 }
2073 
2074 // GL_OES_texture_storage_multisample_2d_array
ValidateTexStorage3DMultisampleOES(const Context * context,TextureType target,GLsizei samples,GLenum sizedinternalformat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedsamplelocations)2075 bool ValidateTexStorage3DMultisampleOES(const Context *context,
2076                                         TextureType target,
2077                                         GLsizei samples,
2078                                         GLenum sizedinternalformat,
2079                                         GLsizei width,
2080                                         GLsizei height,
2081                                         GLsizei depth,
2082                                         GLboolean fixedsamplelocations)
2083 {
2084     if (!context->getExtensions().textureStorageMultisample2DArrayOES)
2085     {
2086         context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
2087         return false;
2088     }
2089 
2090     if (target != TextureType::_2DMultisampleArray)
2091     {
2092         context->validationError(GL_INVALID_ENUM, kTargetMustBeTexture2DMultisampleArrayOES);
2093         return false;
2094     }
2095 
2096     if (width < 1 || height < 1 || depth < 1)
2097     {
2098         context->validationError(GL_INVALID_VALUE, kNegativeSize);
2099         return false;
2100     }
2101 
2102     if (depth > context->getCaps().maxArrayTextureLayers)
2103     {
2104         context->validationError(GL_INVALID_VALUE, kTextureDepthOutOfRange);
2105         return false;
2106     }
2107 
2108     return ValidateTexStorageMultisample(context, target, samples, sizedinternalformat, width,
2109                                          height);
2110 }
2111 
ValidateTexStorageMem3DMultisampleEXT(const Context * context,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedSampleLocations,MemoryObjectID memory,GLuint64 offset)2112 bool ValidateTexStorageMem3DMultisampleEXT(const Context *context,
2113                                            TextureType target,
2114                                            GLsizei samples,
2115                                            GLenum internalFormat,
2116                                            GLsizei width,
2117                                            GLsizei height,
2118                                            GLsizei depth,
2119                                            GLboolean fixedSampleLocations,
2120                                            MemoryObjectID memory,
2121                                            GLuint64 offset)
2122 {
2123     if (!context->getExtensions().memoryObject)
2124     {
2125         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2126         return false;
2127     }
2128 
2129     UNIMPLEMENTED();
2130     return false;
2131 }
2132 
ValidateGetProgramResourceLocationIndexEXT(const Context * context,ShaderProgramID program,GLenum programInterface,const char * name)2133 bool ValidateGetProgramResourceLocationIndexEXT(const Context *context,
2134                                                 ShaderProgramID program,
2135                                                 GLenum programInterface,
2136                                                 const char *name)
2137 {
2138     if (!context->getExtensions().blendFuncExtended)
2139     {
2140         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2141         return false;
2142     }
2143     if (context->getClientVersion() < ES_3_1)
2144     {
2145         context->validationError(GL_INVALID_OPERATION, kES31Required);
2146         return false;
2147     }
2148     if (programInterface != GL_PROGRAM_OUTPUT)
2149     {
2150         context->validationError(GL_INVALID_ENUM, kProgramInterfaceMustBeProgramOutput);
2151         return false;
2152     }
2153     Program *programObject = GetValidProgram(context, program);
2154     if (!programObject)
2155     {
2156         return false;
2157     }
2158     if (!programObject->isLinked())
2159     {
2160         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
2161         return false;
2162     }
2163     return true;
2164 }
2165 
2166 // GL_OES_texture_buffer
ValidateTexBufferOES(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked)2167 bool ValidateTexBufferOES(const Context *context,
2168                           TextureType target,
2169                           GLenum internalformat,
2170                           BufferID bufferPacked)
2171 {
2172     if (!context->getExtensions().textureBufferOES)
2173     {
2174         context->validationError(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable);
2175         return false;
2176     }
2177 
2178     return ValidateTexBufferBase(context, target, internalformat, bufferPacked);
2179 }
2180 
ValidateTexBufferRangeOES(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked,GLintptr offset,GLsizeiptr size)2181 bool ValidateTexBufferRangeOES(const Context *context,
2182                                TextureType target,
2183                                GLenum internalformat,
2184                                BufferID bufferPacked,
2185                                GLintptr offset,
2186                                GLsizeiptr size)
2187 {
2188     if (!context->getExtensions().textureBufferOES)
2189     {
2190         context->validationError(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable);
2191         return false;
2192     }
2193 
2194     return ValidateTexBufferRangeBase(context, target, internalformat, bufferPacked, offset, size);
2195 }
2196 
2197 // GL_EXT_texture_buffer
ValidateTexBufferEXT(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked)2198 bool ValidateTexBufferEXT(const Context *context,
2199                           TextureType target,
2200                           GLenum internalformat,
2201                           BufferID bufferPacked)
2202 {
2203     if (!context->getExtensions().textureBufferEXT)
2204     {
2205         context->validationError(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable);
2206         return false;
2207     }
2208 
2209     return ValidateTexBufferBase(context, target, internalformat, bufferPacked);
2210 }
2211 
ValidateTexBufferRangeEXT(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked,GLintptr offset,GLsizeiptr size)2212 bool ValidateTexBufferRangeEXT(const Context *context,
2213                                TextureType target,
2214                                GLenum internalformat,
2215                                BufferID bufferPacked,
2216                                GLintptr offset,
2217                                GLsizeiptr size)
2218 {
2219     if (!context->getExtensions().textureBufferEXT)
2220     {
2221         context->validationError(GL_INVALID_OPERATION, kTextureBufferExtensionNotAvailable);
2222         return false;
2223     }
2224 
2225     return ValidateTexBufferRangeBase(context, target, internalformat, bufferPacked, offset, size);
2226 }
2227 
ValidateTexBufferBase(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked)2228 bool ValidateTexBufferBase(const Context *context,
2229                            TextureType target,
2230                            GLenum internalformat,
2231                            BufferID bufferPacked)
2232 {
2233     if (target != TextureType::Buffer)
2234     {
2235         context->validationError(GL_INVALID_ENUM, kTextureBufferTarget);
2236         return false;
2237     }
2238 
2239     switch (internalformat)
2240     {
2241         case GL_R8:
2242         case GL_R16F:
2243         case GL_R32F:
2244         case GL_R8I:
2245         case GL_R16I:
2246         case GL_R32I:
2247         case GL_R8UI:
2248         case GL_R16UI:
2249         case GL_R32UI:
2250         case GL_RG8:
2251         case GL_RG16F:
2252         case GL_RG32F:
2253         case GL_RG8I:
2254         case GL_RG16I:
2255         case GL_RG32I:
2256         case GL_RG8UI:
2257         case GL_RG16UI:
2258         case GL_RG32UI:
2259         case GL_RGB32F:
2260         case GL_RGB32I:
2261         case GL_RGB32UI:
2262         case GL_RGBA8:
2263         case GL_RGBA16F:
2264         case GL_RGBA32F:
2265         case GL_RGBA8I:
2266         case GL_RGBA16I:
2267         case GL_RGBA32I:
2268         case GL_RGBA8UI:
2269         case GL_RGBA16UI:
2270         case GL_RGBA32UI:
2271             break;
2272 
2273         default:
2274             context->validationError(GL_INVALID_ENUM, kTextureBufferInternalFormat);
2275             return false;
2276     }
2277 
2278     if (bufferPacked.value != 0)
2279     {
2280         if (!context->isBufferGenerated(bufferPacked))
2281         {
2282             context->validationError(GL_INVALID_OPERATION, kTextureBufferInvalidBuffer);
2283             return false;
2284         }
2285     }
2286 
2287     return true;
2288 }
2289 
ValidateTexBufferRangeBase(const Context * context,TextureType target,GLenum internalformat,BufferID bufferPacked,GLintptr offset,GLsizeiptr size)2290 bool ValidateTexBufferRangeBase(const Context *context,
2291                                 TextureType target,
2292                                 GLenum internalformat,
2293                                 BufferID bufferPacked,
2294                                 GLintptr offset,
2295                                 GLsizeiptr size)
2296 {
2297     const Caps &caps = context->getCaps();
2298 
2299     if (offset < 0 || (offset % caps.textureBufferOffsetAlignment) != 0)
2300     {
2301         context->validationError(GL_INVALID_VALUE, kTextureBufferOffsetAlignment);
2302         return false;
2303     }
2304     if (size <= 0)
2305     {
2306         context->validationError(GL_INVALID_VALUE, kTextureBufferSize);
2307         return false;
2308     }
2309     const Buffer *buffer = context->getBuffer(bufferPacked);
2310     if (offset + size > buffer->getSize())
2311     {
2312         context->validationError(GL_INVALID_VALUE, kTextureBufferSizeOffset);
2313         return false;
2314     }
2315 
2316     return ValidateTexBufferBase(context, target, internalformat, bufferPacked);
2317 }
2318 
2319 }  // namespace gl
2320