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