1 //
2 // Copyright (c) 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.h"
10 
11 #include "libANGLE/Context.h"
12 #include "libANGLE/ErrorStrings.h"
13 #include "libANGLE/Framebuffer.h"
14 #include "libANGLE/VertexArray.h"
15 #include "libANGLE/validationES.h"
16 #include "libANGLE/validationES2.h"
17 #include "libANGLE/validationES3.h"
18 
19 #include "common/utilities.h"
20 
21 using namespace angle;
22 
23 namespace gl
24 {
25 
26 namespace
27 {
28 
ValidateNamedProgramInterface(GLenum programInterface)29 bool ValidateNamedProgramInterface(GLenum programInterface)
30 {
31     switch (programInterface)
32     {
33         case GL_UNIFORM:
34         case GL_UNIFORM_BLOCK:
35         case GL_PROGRAM_INPUT:
36         case GL_PROGRAM_OUTPUT:
37         case GL_TRANSFORM_FEEDBACK_VARYING:
38         case GL_BUFFER_VARIABLE:
39         case GL_SHADER_STORAGE_BLOCK:
40             return true;
41         default:
42             return false;
43     }
44 }
45 
ValidateLocationProgramInterface(GLenum programInterface)46 bool ValidateLocationProgramInterface(GLenum programInterface)
47 {
48     switch (programInterface)
49     {
50         case GL_UNIFORM:
51         case GL_PROGRAM_INPUT:
52         case GL_PROGRAM_OUTPUT:
53             return true;
54         default:
55             return false;
56     }
57 }
58 
ValidateProgramInterface(GLenum programInterface)59 bool ValidateProgramInterface(GLenum programInterface)
60 {
61     return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
62             ValidateNamedProgramInterface(programInterface));
63 }
64 
ValidateProgramResourceProperty(GLenum prop)65 bool ValidateProgramResourceProperty(GLenum prop)
66 {
67     switch (prop)
68     {
69         case GL_ACTIVE_VARIABLES:
70         case GL_BUFFER_BINDING:
71         case GL_NUM_ACTIVE_VARIABLES:
72 
73         case GL_ARRAY_SIZE:
74 
75         case GL_ARRAY_STRIDE:
76         case GL_BLOCK_INDEX:
77         case GL_IS_ROW_MAJOR:
78         case GL_MATRIX_STRIDE:
79 
80         case GL_ATOMIC_COUNTER_BUFFER_INDEX:
81 
82         case GL_BUFFER_DATA_SIZE:
83 
84         case GL_LOCATION:
85 
86         case GL_NAME_LENGTH:
87 
88         case GL_OFFSET:
89 
90         case GL_REFERENCED_BY_VERTEX_SHADER:
91         case GL_REFERENCED_BY_FRAGMENT_SHADER:
92         case GL_REFERENCED_BY_COMPUTE_SHADER:
93 
94         case GL_TOP_LEVEL_ARRAY_SIZE:
95         case GL_TOP_LEVEL_ARRAY_STRIDE:
96 
97         case GL_TYPE:
98             return true;
99 
100         default:
101             return false;
102     }
103 }
104 
105 // GLES 3.10 spec: Page 82 -- Table 7.2
ValidateProgramResourcePropertyByInterface(GLenum prop,GLenum programInterface)106 bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
107 {
108     switch (prop)
109     {
110         case GL_ACTIVE_VARIABLES:
111         case GL_BUFFER_BINDING:
112         case GL_NUM_ACTIVE_VARIABLES:
113         {
114             switch (programInterface)
115             {
116                 case GL_ATOMIC_COUNTER_BUFFER:
117                 case GL_SHADER_STORAGE_BLOCK:
118                 case GL_UNIFORM_BLOCK:
119                     return true;
120                 default:
121                     return false;
122             }
123         }
124 
125         case GL_ARRAY_SIZE:
126         {
127             switch (programInterface)
128             {
129                 case GL_BUFFER_VARIABLE:
130                 case GL_PROGRAM_INPUT:
131                 case GL_PROGRAM_OUTPUT:
132                 case GL_TRANSFORM_FEEDBACK_VARYING:
133                 case GL_UNIFORM:
134                     return true;
135                 default:
136                     return false;
137             }
138         }
139 
140         case GL_ARRAY_STRIDE:
141         case GL_BLOCK_INDEX:
142         case GL_IS_ROW_MAJOR:
143         case GL_MATRIX_STRIDE:
144         {
145             switch (programInterface)
146             {
147                 case GL_BUFFER_VARIABLE:
148                 case GL_UNIFORM:
149                     return true;
150                 default:
151                     return false;
152             }
153         }
154 
155         case GL_ATOMIC_COUNTER_BUFFER_INDEX:
156         {
157             if (programInterface == GL_UNIFORM)
158             {
159                 return true;
160             }
161             return false;
162         }
163 
164         case GL_BUFFER_DATA_SIZE:
165         {
166             switch (programInterface)
167             {
168                 case GL_ATOMIC_COUNTER_BUFFER:
169                 case GL_SHADER_STORAGE_BLOCK:
170                 case GL_UNIFORM_BLOCK:
171                     return true;
172                 default:
173                     return false;
174             }
175         }
176 
177         case GL_LOCATION:
178         {
179             return ValidateLocationProgramInterface(programInterface);
180         }
181 
182         case GL_NAME_LENGTH:
183         {
184             return ValidateNamedProgramInterface(programInterface);
185         }
186 
187         case GL_OFFSET:
188         {
189             switch (programInterface)
190             {
191                 case GL_BUFFER_VARIABLE:
192                 case GL_UNIFORM:
193                     return true;
194                 default:
195                     return false;
196             }
197         }
198 
199         case GL_REFERENCED_BY_VERTEX_SHADER:
200         case GL_REFERENCED_BY_FRAGMENT_SHADER:
201         case GL_REFERENCED_BY_COMPUTE_SHADER:
202         {
203             switch (programInterface)
204             {
205                 case GL_ATOMIC_COUNTER_BUFFER:
206                 case GL_BUFFER_VARIABLE:
207                 case GL_PROGRAM_INPUT:
208                 case GL_PROGRAM_OUTPUT:
209                 case GL_SHADER_STORAGE_BLOCK:
210                 case GL_UNIFORM:
211                 case GL_UNIFORM_BLOCK:
212                     return true;
213                 default:
214                     return false;
215             }
216         }
217 
218         case GL_TOP_LEVEL_ARRAY_SIZE:
219         case GL_TOP_LEVEL_ARRAY_STRIDE:
220         {
221             if (programInterface == GL_BUFFER_VARIABLE)
222             {
223                 return true;
224             }
225             return false;
226         }
227 
228         case GL_TYPE:
229         {
230             switch (programInterface)
231             {
232                 case GL_BUFFER_VARIABLE:
233                 case GL_PROGRAM_INPUT:
234                 case GL_PROGRAM_OUTPUT:
235                 case GL_TRANSFORM_FEEDBACK_VARYING:
236                 case GL_UNIFORM:
237                     return true;
238                 default:
239                     return false;
240             }
241         }
242 
243         default:
244             return false;
245     }
246 }
247 
ValidateProgramResourceIndex(const Program * programObject,GLenum programInterface,GLuint index)248 bool ValidateProgramResourceIndex(const Program *programObject,
249                                   GLenum programInterface,
250                                   GLuint index)
251 {
252     switch (programInterface)
253     {
254         case GL_PROGRAM_INPUT:
255             return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
256 
257         case GL_PROGRAM_OUTPUT:
258             return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
259 
260         case GL_UNIFORM:
261             return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
262 
263         case GL_BUFFER_VARIABLE:
264             return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
265 
266         case GL_SHADER_STORAGE_BLOCK:
267             return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
268 
269         case GL_UNIFORM_BLOCK:
270             return (index < programObject->getActiveUniformBlockCount());
271 
272         case GL_ATOMIC_COUNTER_BUFFER:
273             return (index < programObject->getActiveAtomicCounterBufferCount());
274 
275         // TODO(jie.a.chen@intel.com): more interfaces.
276         case GL_TRANSFORM_FEEDBACK_VARYING:
277             UNIMPLEMENTED();
278             return false;
279 
280         default:
281             UNREACHABLE();
282             return false;
283     }
284 }
285 
ValidateProgramUniform(gl::Context * context,GLenum valueType,GLuint program,GLint location,GLsizei count)286 bool ValidateProgramUniform(gl::Context *context,
287                             GLenum valueType,
288                             GLuint program,
289                             GLint location,
290                             GLsizei count)
291 {
292     // Check for ES31 program uniform entry points
293     if (context->getClientVersion() < Version(3, 1))
294     {
295         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
296         return false;
297     }
298 
299     const LinkedUniform *uniform = nullptr;
300     gl::Program *programObject   = GetValidProgram(context, program);
301     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
302            ValidateUniformValue(context, valueType, uniform->type);
303 }
304 
ValidateProgramUniformMatrix(gl::Context * context,GLenum valueType,GLuint program,GLint location,GLsizei count,GLboolean transpose)305 bool ValidateProgramUniformMatrix(gl::Context *context,
306                                   GLenum valueType,
307                                   GLuint program,
308                                   GLint location,
309                                   GLsizei count,
310                                   GLboolean transpose)
311 {
312     // Check for ES31 program uniform entry points
313     if (context->getClientVersion() < Version(3, 1))
314     {
315         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
316         return false;
317     }
318 
319     const LinkedUniform *uniform = nullptr;
320     gl::Program *programObject   = GetValidProgram(context, program);
321     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
322            ValidateUniformMatrixValue(context, valueType, uniform->type);
323 }
324 
ValidateVertexAttribFormatCommon(ValidationContext * context,GLuint attribIndex,GLint size,GLenum type,GLuint relativeOffset,GLboolean pureInteger)325 bool ValidateVertexAttribFormatCommon(ValidationContext *context,
326                                       GLuint attribIndex,
327                                       GLint size,
328                                       GLenum type,
329                                       GLuint relativeOffset,
330                                       GLboolean pureInteger)
331 {
332     if (context->getClientVersion() < ES_3_1)
333     {
334         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
335         return false;
336     }
337 
338     const Caps &caps = context->getCaps();
339     if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
340     {
341         context->handleError(
342             InvalidValue()
343             << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
344         return false;
345     }
346 
347     // [OpenGL ES 3.1] Section 10.3.1 page 243:
348     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
349     if (context->getGLState().getVertexArrayId() == 0)
350     {
351         context->handleError(InvalidOperation() << "Default vertex array object is bound.");
352         return false;
353     }
354 
355     return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
356 }
357 
358 }  // anonymous namespace
359 
ValidateGetBooleani_v(Context * context,GLenum target,GLuint index,GLboolean * data)360 bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
361 {
362     if (context->getClientVersion() < ES_3_1)
363     {
364         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
365         return false;
366     }
367 
368     if (!ValidateIndexedStateQuery(context, target, index, nullptr))
369     {
370         return false;
371     }
372 
373     return true;
374 }
375 
ValidateGetBooleani_vRobustANGLE(Context * context,GLenum target,GLuint index,GLsizei bufSize,GLsizei * length,GLboolean * data)376 bool ValidateGetBooleani_vRobustANGLE(Context *context,
377                                       GLenum target,
378                                       GLuint index,
379                                       GLsizei bufSize,
380                                       GLsizei *length,
381                                       GLboolean *data)
382 {
383     if (context->getClientVersion() < ES_3_1)
384     {
385         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
386         return false;
387     }
388 
389     if (!ValidateRobustEntryPoint(context, bufSize))
390     {
391         return false;
392     }
393 
394     if (!ValidateIndexedStateQuery(context, target, index, length))
395     {
396         return false;
397     }
398 
399     if (!ValidateRobustBufferSize(context, bufSize, *length))
400     {
401         return false;
402     }
403 
404     return true;
405 }
406 
ValidateDrawIndirectBase(Context * context,GLenum mode,const void * indirect)407 bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
408 {
409     if (context->getClientVersion() < ES_3_1)
410     {
411         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
412         return false;
413     }
414 
415     // Here the third parameter 1 is only to pass the count validation.
416     if (!ValidateDrawBase(context, mode, 1))
417     {
418         return false;
419     }
420 
421     const State &state = context->getGLState();
422 
423     // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
424     // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
425     if (!state.getVertexArrayId())
426     {
427         context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
428         return false;
429     }
430 
431     gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
432     if (!drawIndirectBuffer)
433     {
434         context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
435         return false;
436     }
437 
438     // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
439     // machine units, of uint.
440     GLint64 offset = reinterpret_cast<GLint64>(indirect);
441     if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
442     {
443         context->handleError(
444             InvalidValue()
445             << "indirect is not a multiple of the size, in basic machine units, of uint");
446         return false;
447     }
448 
449     // ANGLE_multiview spec, revision 1:
450     // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
451     // number of views in the draw framebuffer is greater than 1.
452     const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
453     ASSERT(drawFramebuffer != nullptr);
454     if (drawFramebuffer->getNumViews() > 1)
455     {
456         context->handleError(
457             InvalidOperation()
458             << "The number of views in the active draw framebuffer is greater than 1.");
459         return false;
460     }
461 
462     return true;
463 }
464 
ValidateDrawArraysIndirect(Context * context,GLenum mode,const void * indirect)465 bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
466 {
467     const State &state                          = context->getGLState();
468     gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
469     if (curTransformFeedback && curTransformFeedback->isActive() &&
470         !curTransformFeedback->isPaused())
471     {
472         // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
473         context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
474         return false;
475     }
476 
477     if (!ValidateDrawIndirectBase(context, mode, indirect))
478         return false;
479 
480     gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
481     CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
482     // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
483     // which's size is 4 * sizeof(uint).
484     auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
485     if (!checkedSum.IsValid() ||
486         checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
487     {
488         context->handleError(
489             InvalidOperation()
490             << "the  command  would source data beyond the end of the buffer object.");
491         return false;
492     }
493 
494     return true;
495 }
496 
ValidateDrawElementsIndirect(Context * context,GLenum mode,GLenum type,const void * indirect)497 bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
498 {
499     if (!ValidateDrawElementsBase(context, type))
500         return false;
501 
502     const State &state             = context->getGLState();
503     const VertexArray *vao         = state.getVertexArray();
504     gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
505     if (!elementArrayBuffer)
506     {
507         context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
508         return false;
509     }
510 
511     if (!ValidateDrawIndirectBase(context, mode, indirect))
512         return false;
513 
514     gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
515     CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
516     // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
517     // which's size is 5 * sizeof(uint).
518     auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
519     if (!checkedSum.IsValid() ||
520         checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
521     {
522         context->handleError(
523             InvalidOperation()
524             << "the  command  would source data beyond the end of the buffer object.");
525         return false;
526     }
527 
528     return true;
529 }
530 
ValidateProgramUniform1i(Context * context,GLuint program,GLint location,GLint v0)531 bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
532 {
533     return ValidateProgramUniform1iv(context, program, location, 1, &v0);
534 }
535 
ValidateProgramUniform2i(Context * context,GLuint program,GLint location,GLint v0,GLint v1)536 bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
537 {
538     GLint xy[2] = {v0, v1};
539     return ValidateProgramUniform2iv(context, program, location, 1, xy);
540 }
541 
ValidateProgramUniform3i(Context * context,GLuint program,GLint location,GLint v0,GLint v1,GLint v2)542 bool ValidateProgramUniform3i(Context *context,
543                               GLuint program,
544                               GLint location,
545                               GLint v0,
546                               GLint v1,
547                               GLint v2)
548 {
549     GLint xyz[3] = {v0, v1, v2};
550     return ValidateProgramUniform3iv(context, program, location, 1, xyz);
551 }
552 
ValidateProgramUniform4i(Context * context,GLuint program,GLint location,GLint v0,GLint v1,GLint v2,GLint v3)553 bool ValidateProgramUniform4i(Context *context,
554                               GLuint program,
555                               GLint location,
556                               GLint v0,
557                               GLint v1,
558                               GLint v2,
559                               GLint v3)
560 {
561     GLint xyzw[4] = {v0, v1, v2, v3};
562     return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
563 }
564 
ValidateProgramUniform1ui(Context * context,GLuint program,GLint location,GLuint v0)565 bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
566 {
567     return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
568 }
569 
ValidateProgramUniform2ui(Context * context,GLuint program,GLint location,GLuint v0,GLuint v1)570 bool ValidateProgramUniform2ui(Context *context,
571                                GLuint program,
572                                GLint location,
573                                GLuint v0,
574                                GLuint v1)
575 {
576     GLuint xy[2] = {v0, v1};
577     return ValidateProgramUniform2uiv(context, program, location, 1, xy);
578 }
579 
ValidateProgramUniform3ui(Context * context,GLuint program,GLint location,GLuint v0,GLuint v1,GLuint v2)580 bool ValidateProgramUniform3ui(Context *context,
581                                GLuint program,
582                                GLint location,
583                                GLuint v0,
584                                GLuint v1,
585                                GLuint v2)
586 {
587     GLuint xyz[3] = {v0, v1, v2};
588     return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
589 }
590 
ValidateProgramUniform4ui(Context * context,GLuint program,GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)591 bool ValidateProgramUniform4ui(Context *context,
592                                GLuint program,
593                                GLint location,
594                                GLuint v0,
595                                GLuint v1,
596                                GLuint v2,
597                                GLuint v3)
598 {
599     GLuint xyzw[4] = {v0, v1, v2, v3};
600     return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
601 }
602 
ValidateProgramUniform1f(Context * context,GLuint program,GLint location,GLfloat v0)603 bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
604 {
605     return ValidateProgramUniform1fv(context, program, location, 1, &v0);
606 }
607 
ValidateProgramUniform2f(Context * context,GLuint program,GLint location,GLfloat v0,GLfloat v1)608 bool ValidateProgramUniform2f(Context *context,
609                               GLuint program,
610                               GLint location,
611                               GLfloat v0,
612                               GLfloat v1)
613 {
614     GLfloat xy[2] = {v0, v1};
615     return ValidateProgramUniform2fv(context, program, location, 1, xy);
616 }
617 
ValidateProgramUniform3f(Context * context,GLuint program,GLint location,GLfloat v0,GLfloat v1,GLfloat v2)618 bool ValidateProgramUniform3f(Context *context,
619                               GLuint program,
620                               GLint location,
621                               GLfloat v0,
622                               GLfloat v1,
623                               GLfloat v2)
624 {
625     GLfloat xyz[3] = {v0, v1, v2};
626     return ValidateProgramUniform3fv(context, program, location, 1, xyz);
627 }
628 
ValidateProgramUniform4f(Context * context,GLuint program,GLint location,GLfloat v0,GLfloat v1,GLfloat v2,GLfloat v3)629 bool ValidateProgramUniform4f(Context *context,
630                               GLuint program,
631                               GLint location,
632                               GLfloat v0,
633                               GLfloat v1,
634                               GLfloat v2,
635                               GLfloat v3)
636 {
637     GLfloat xyzw[4] = {v0, v1, v2, v3};
638     return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
639 }
640 
ValidateProgramUniform1iv(Context * context,GLuint program,GLint location,GLsizei count,const GLint * value)641 bool ValidateProgramUniform1iv(Context *context,
642                                GLuint program,
643                                GLint location,
644                                GLsizei count,
645                                const GLint *value)
646 {
647     // Check for ES31 program uniform entry points
648     if (context->getClientVersion() < Version(3, 1))
649     {
650         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
651         return false;
652     }
653 
654     const LinkedUniform *uniform = nullptr;
655     gl::Program *programObject   = GetValidProgram(context, program);
656     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
657            ValidateUniform1ivValue(context, uniform->type, count, value);
658 }
659 
ValidateProgramUniform2iv(Context * context,GLuint program,GLint location,GLsizei count,const GLint * value)660 bool ValidateProgramUniform2iv(Context *context,
661                                GLuint program,
662                                GLint location,
663                                GLsizei count,
664                                const GLint *value)
665 {
666     return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
667 }
668 
ValidateProgramUniform3iv(Context * context,GLuint program,GLint location,GLsizei count,const GLint * value)669 bool ValidateProgramUniform3iv(Context *context,
670                                GLuint program,
671                                GLint location,
672                                GLsizei count,
673                                const GLint *value)
674 {
675     return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
676 }
677 
ValidateProgramUniform4iv(Context * context,GLuint program,GLint location,GLsizei count,const GLint * value)678 bool ValidateProgramUniform4iv(Context *context,
679                                GLuint program,
680                                GLint location,
681                                GLsizei count,
682                                const GLint *value)
683 {
684     return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
685 }
686 
ValidateProgramUniform1uiv(Context * context,GLuint program,GLint location,GLsizei count,const GLuint * value)687 bool ValidateProgramUniform1uiv(Context *context,
688                                 GLuint program,
689                                 GLint location,
690                                 GLsizei count,
691                                 const GLuint *value)
692 {
693     return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
694 }
695 
ValidateProgramUniform2uiv(Context * context,GLuint program,GLint location,GLsizei count,const GLuint * value)696 bool ValidateProgramUniform2uiv(Context *context,
697                                 GLuint program,
698                                 GLint location,
699                                 GLsizei count,
700                                 const GLuint *value)
701 {
702     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
703 }
704 
ValidateProgramUniform3uiv(Context * context,GLuint program,GLint location,GLsizei count,const GLuint * value)705 bool ValidateProgramUniform3uiv(Context *context,
706                                 GLuint program,
707                                 GLint location,
708                                 GLsizei count,
709                                 const GLuint *value)
710 {
711     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
712 }
713 
ValidateProgramUniform4uiv(Context * context,GLuint program,GLint location,GLsizei count,const GLuint * value)714 bool ValidateProgramUniform4uiv(Context *context,
715                                 GLuint program,
716                                 GLint location,
717                                 GLsizei count,
718                                 const GLuint *value)
719 {
720     return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
721 }
722 
ValidateProgramUniform1fv(Context * context,GLuint program,GLint location,GLsizei count,const GLfloat * value)723 bool ValidateProgramUniform1fv(Context *context,
724                                GLuint program,
725                                GLint location,
726                                GLsizei count,
727                                const GLfloat *value)
728 {
729     return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
730 }
731 
ValidateProgramUniform2fv(Context * context,GLuint program,GLint location,GLsizei count,const GLfloat * value)732 bool ValidateProgramUniform2fv(Context *context,
733                                GLuint program,
734                                GLint location,
735                                GLsizei count,
736                                const GLfloat *value)
737 {
738     return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
739 }
740 
ValidateProgramUniform3fv(Context * context,GLuint program,GLint location,GLsizei count,const GLfloat * value)741 bool ValidateProgramUniform3fv(Context *context,
742                                GLuint program,
743                                GLint location,
744                                GLsizei count,
745                                const GLfloat *value)
746 {
747     return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
748 }
749 
ValidateProgramUniform4fv(Context * context,GLuint program,GLint location,GLsizei count,const GLfloat * value)750 bool ValidateProgramUniform4fv(Context *context,
751                                GLuint program,
752                                GLint location,
753                                GLsizei count,
754                                const GLfloat *value)
755 {
756     return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
757 }
758 
ValidateProgramUniformMatrix2fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)759 bool ValidateProgramUniformMatrix2fv(Context *context,
760                                      GLuint program,
761                                      GLint location,
762                                      GLsizei count,
763                                      GLboolean transpose,
764                                      const GLfloat *value)
765 {
766     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
767                                         transpose);
768 }
769 
ValidateProgramUniformMatrix3fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)770 bool ValidateProgramUniformMatrix3fv(Context *context,
771                                      GLuint program,
772                                      GLint location,
773                                      GLsizei count,
774                                      GLboolean transpose,
775                                      const GLfloat *value)
776 {
777     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
778                                         transpose);
779 }
780 
ValidateProgramUniformMatrix4fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)781 bool ValidateProgramUniformMatrix4fv(Context *context,
782                                      GLuint program,
783                                      GLint location,
784                                      GLsizei count,
785                                      GLboolean transpose,
786                                      const GLfloat *value)
787 {
788     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
789                                         transpose);
790 }
791 
ValidateProgramUniformMatrix2x3fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)792 bool ValidateProgramUniformMatrix2x3fv(Context *context,
793                                        GLuint program,
794                                        GLint location,
795                                        GLsizei count,
796                                        GLboolean transpose,
797                                        const GLfloat *value)
798 {
799     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
800                                         transpose);
801 }
802 
ValidateProgramUniformMatrix3x2fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)803 bool ValidateProgramUniformMatrix3x2fv(Context *context,
804                                        GLuint program,
805                                        GLint location,
806                                        GLsizei count,
807                                        GLboolean transpose,
808                                        const GLfloat *value)
809 {
810     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
811                                         transpose);
812 }
813 
ValidateProgramUniformMatrix2x4fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)814 bool ValidateProgramUniformMatrix2x4fv(Context *context,
815                                        GLuint program,
816                                        GLint location,
817                                        GLsizei count,
818                                        GLboolean transpose,
819                                        const GLfloat *value)
820 {
821     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
822                                         transpose);
823 }
824 
ValidateProgramUniformMatrix4x2fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)825 bool ValidateProgramUniformMatrix4x2fv(Context *context,
826                                        GLuint program,
827                                        GLint location,
828                                        GLsizei count,
829                                        GLboolean transpose,
830                                        const GLfloat *value)
831 {
832     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
833                                         transpose);
834 }
835 
ValidateProgramUniformMatrix3x4fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)836 bool ValidateProgramUniformMatrix3x4fv(Context *context,
837                                        GLuint program,
838                                        GLint location,
839                                        GLsizei count,
840                                        GLboolean transpose,
841                                        const GLfloat *value)
842 {
843     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
844                                         transpose);
845 }
846 
ValidateProgramUniformMatrix4x3fv(Context * context,GLuint program,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)847 bool ValidateProgramUniformMatrix4x3fv(Context *context,
848                                        GLuint program,
849                                        GLint location,
850                                        GLsizei count,
851                                        GLboolean transpose,
852                                        const GLfloat *value)
853 {
854     return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
855                                         transpose);
856 }
857 
ValidateGetTexLevelParameterBase(Context * context,GLenum target,GLint level,GLenum pname,GLsizei * length)858 bool ValidateGetTexLevelParameterBase(Context *context,
859                                       GLenum target,
860                                       GLint level,
861                                       GLenum pname,
862                                       GLsizei *length)
863 {
864     if (context->getClientVersion() < ES_3_1)
865     {
866         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
867         return false;
868     }
869 
870     if (length)
871     {
872         *length = 0;
873     }
874 
875     if (!ValidTexLevelDestinationTarget(context, target))
876     {
877         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
878         return false;
879     }
880 
881     if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
882         nullptr)
883     {
884         context->handleError(InvalidEnum() << "No texture bound.");
885         return false;
886     }
887 
888     if (!ValidMipLevel(context, target, level))
889     {
890         context->handleError(InvalidValue());
891         return false;
892     }
893 
894     switch (pname)
895     {
896         case GL_TEXTURE_RED_TYPE:
897         case GL_TEXTURE_GREEN_TYPE:
898         case GL_TEXTURE_BLUE_TYPE:
899         case GL_TEXTURE_ALPHA_TYPE:
900         case GL_TEXTURE_DEPTH_TYPE:
901             break;
902         case GL_TEXTURE_RED_SIZE:
903         case GL_TEXTURE_GREEN_SIZE:
904         case GL_TEXTURE_BLUE_SIZE:
905         case GL_TEXTURE_ALPHA_SIZE:
906         case GL_TEXTURE_DEPTH_SIZE:
907         case GL_TEXTURE_STENCIL_SIZE:
908         case GL_TEXTURE_SHARED_SIZE:
909             break;
910         case GL_TEXTURE_INTERNAL_FORMAT:
911         case GL_TEXTURE_WIDTH:
912         case GL_TEXTURE_HEIGHT:
913         case GL_TEXTURE_DEPTH:
914             break;
915         case GL_TEXTURE_SAMPLES:
916         case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
917             break;
918         case GL_TEXTURE_COMPRESSED:
919             break;
920         default:
921             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
922             return false;
923     }
924 
925     if (length)
926     {
927         *length = 1;
928     }
929     return true;
930 }
931 
ValidateGetTexLevelParameterfv(Context * context,GLenum target,GLint level,GLenum pname,GLfloat * params)932 bool ValidateGetTexLevelParameterfv(Context *context,
933                                     GLenum target,
934                                     GLint level,
935                                     GLenum pname,
936                                     GLfloat *params)
937 {
938     return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
939 }
940 
ValidateGetTexLevelParameteriv(Context * context,GLenum target,GLint level,GLenum pname,GLint * params)941 bool ValidateGetTexLevelParameteriv(Context *context,
942                                     GLenum target,
943                                     GLint level,
944                                     GLenum pname,
945                                     GLint *params)
946 {
947     return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
948 }
949 
ValidateTexStorage2DMultisample(Context * context,GLenum target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)950 bool ValidateTexStorage2DMultisample(Context *context,
951                                      GLenum target,
952                                      GLsizei samples,
953                                      GLint internalFormat,
954                                      GLsizei width,
955                                      GLsizei height,
956                                      GLboolean fixedSampleLocations)
957 {
958     if (context->getClientVersion() < ES_3_1)
959     {
960         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
961         return false;
962     }
963 
964     if (target != GL_TEXTURE_2D_MULTISAMPLE)
965     {
966         context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
967         return false;
968     }
969 
970     if (width < 1 || height < 1)
971     {
972         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
973         return false;
974     }
975 
976     const Caps &caps = context->getCaps();
977     if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
978         static_cast<GLuint>(height) > caps.max2DTextureSize)
979     {
980         context
981             ->handleError(InvalidValue()
982                           << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
983         return false;
984     }
985 
986     if (samples == 0)
987     {
988         context->handleError(InvalidValue() << "Samples may not be zero.");
989         return false;
990     }
991 
992     const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
993     if (!formatCaps.renderable)
994     {
995         context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
996                                               "depth-renderable, or stencil-renderable.");
997         return false;
998     }
999 
1000     // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
1001     // is one of the unsized base internalformats listed in table 8.11.
1002     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1003     if (formatInfo.internalFormat == GL_NONE)
1004     {
1005         context->handleError(
1006             InvalidEnum()
1007             << "Internalformat is one of the unsupported unsized base internalformats.");
1008         return false;
1009     }
1010 
1011     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1012     {
1013         context->handleError(
1014             InvalidOperation()
1015             << "Samples must not be greater than maximum supported value for the format.");
1016         return false;
1017     }
1018 
1019     Texture *texture = context->getTargetTexture(target);
1020     if (!texture || texture->id() == 0)
1021     {
1022         context->handleError(InvalidOperation() << "Zero is bound to target.");
1023         return false;
1024     }
1025 
1026     if (texture->getImmutableFormat())
1027     {
1028         context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
1029                                                    "the texture currently bound to target on "
1030                                                    "the active texture unit is true.");
1031         return false;
1032     }
1033 
1034     return true;
1035 }
1036 
ValidateGetMultisamplefv(Context * context,GLenum pname,GLuint index,GLfloat * val)1037 bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
1038 {
1039     if (context->getClientVersion() < ES_3_1)
1040     {
1041         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1042         return false;
1043     }
1044 
1045     if (pname != GL_SAMPLE_POSITION)
1046     {
1047         context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
1048         return false;
1049     }
1050 
1051     Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
1052 
1053     if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
1054     {
1055         context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
1056         return false;
1057     }
1058 
1059     return true;
1060 }
1061 
ValidateFramebufferParameteri(Context * context,GLenum target,GLenum pname,GLint param)1062 bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
1063 {
1064     if (context->getClientVersion() < ES_3_1)
1065     {
1066         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1067         return false;
1068     }
1069 
1070     if (!ValidFramebufferTarget(context, target))
1071     {
1072         context->handleError(InvalidEnum() << "Invalid framebuffer target.");
1073         return false;
1074     }
1075 
1076     switch (pname)
1077     {
1078         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1079         {
1080             GLint maxWidth = context->getCaps().maxFramebufferWidth;
1081             if (param < 0 || param > maxWidth)
1082             {
1083                 context->handleError(
1084                     InvalidValue()
1085                     << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
1086                 return false;
1087             }
1088             break;
1089         }
1090         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1091         {
1092             GLint maxHeight = context->getCaps().maxFramebufferHeight;
1093             if (param < 0 || param > maxHeight)
1094             {
1095                 context->handleError(
1096                     InvalidValue()
1097                     << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
1098                 return false;
1099             }
1100             break;
1101         }
1102         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1103         {
1104             GLint maxSamples = context->getCaps().maxFramebufferSamples;
1105             if (param < 0 || param > maxSamples)
1106             {
1107                 context->handleError(
1108                     InvalidValue()
1109                     << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
1110                 return false;
1111             }
1112             break;
1113         }
1114         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1115         {
1116             break;
1117         }
1118         default:
1119         {
1120             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
1121             return false;
1122         }
1123     }
1124 
1125     const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1126     ASSERT(framebuffer);
1127     if (framebuffer->id() == 0)
1128     {
1129         context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
1130         return false;
1131     }
1132     return true;
1133 }
1134 
ValidateGetFramebufferParameteriv(Context * context,GLenum target,GLenum pname,GLint * params)1135 bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
1136 {
1137     if (context->getClientVersion() < ES_3_1)
1138     {
1139         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1140         return false;
1141     }
1142 
1143     if (!ValidFramebufferTarget(context, target))
1144     {
1145         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
1146         return false;
1147     }
1148 
1149     switch (pname)
1150     {
1151         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1152         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1153         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1154         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1155             break;
1156         default:
1157             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
1158             return false;
1159     }
1160 
1161     const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1162     ASSERT(framebuffer);
1163 
1164     if (framebuffer->id() == 0)
1165     {
1166         context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
1167         return false;
1168     }
1169     return true;
1170 }
1171 
ValidateGetProgramResourceIndex(Context * context,GLuint program,GLenum programInterface,const GLchar * name)1172 bool ValidateGetProgramResourceIndex(Context *context,
1173                                      GLuint program,
1174                                      GLenum programInterface,
1175                                      const GLchar *name)
1176 {
1177     if (context->getClientVersion() < ES_3_1)
1178     {
1179         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1180         return false;
1181     }
1182 
1183     Program *programObject = GetValidProgram(context, program);
1184     if (programObject == nullptr)
1185     {
1186         return false;
1187     }
1188 
1189     if (!ValidateNamedProgramInterface(programInterface))
1190     {
1191         context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1192                                            << std::uppercase << programInterface);
1193         return false;
1194     }
1195 
1196     return true;
1197 }
1198 
ValidateBindVertexBuffer(ValidationContext * context,GLuint bindingIndex,GLuint buffer,GLintptr offset,GLsizei stride)1199 bool ValidateBindVertexBuffer(ValidationContext *context,
1200                               GLuint bindingIndex,
1201                               GLuint buffer,
1202                               GLintptr offset,
1203                               GLsizei stride)
1204 {
1205     if (context->getClientVersion() < ES_3_1)
1206     {
1207         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1208         return false;
1209     }
1210 
1211     if (!context->isBufferGenerated(buffer))
1212     {
1213         context->handleError(InvalidOperation() << "Buffer is not generated.");
1214         return false;
1215     }
1216 
1217     const Caps &caps = context->getCaps();
1218     if (bindingIndex >= caps.maxVertexAttribBindings)
1219     {
1220         context->handleError(InvalidValue()
1221                              << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
1222         return false;
1223     }
1224 
1225     if (offset < 0)
1226     {
1227         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
1228         return false;
1229     }
1230 
1231     if (stride < 0 || stride > caps.maxVertexAttribStride)
1232     {
1233         context->handleError(InvalidValue()
1234                              << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
1235         return false;
1236     }
1237 
1238     // [OpenGL ES 3.1] Section 10.3.1 page 244:
1239     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1240     if (context->getGLState().getVertexArrayId() == 0)
1241     {
1242         context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
1243         return false;
1244     }
1245 
1246     return true;
1247 }
1248 
ValidateVertexBindingDivisor(ValidationContext * context,GLuint bindingIndex,GLuint divisor)1249 bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
1250 {
1251     if (context->getClientVersion() < ES_3_1)
1252     {
1253         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1254         return false;
1255     }
1256 
1257     const Caps &caps = context->getCaps();
1258     if (bindingIndex >= caps.maxVertexAttribBindings)
1259     {
1260         context->handleError(InvalidValue()
1261                              << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
1262         return false;
1263     }
1264 
1265     // [OpenGL ES 3.1] Section 10.3.1 page 243:
1266     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1267     if (context->getGLState().getVertexArrayId() == 0)
1268     {
1269         context->handleError(InvalidOperation() << "Default vertex array object is bound.");
1270         return false;
1271     }
1272 
1273     return true;
1274 }
1275 
ValidateVertexAttribFormat(ValidationContext * context,GLuint attribindex,GLint size,GLenum type,GLboolean normalized,GLuint relativeoffset)1276 bool ValidateVertexAttribFormat(ValidationContext *context,
1277                                 GLuint attribindex,
1278                                 GLint size,
1279                                 GLenum type,
1280                                 GLboolean normalized,
1281                                 GLuint relativeoffset)
1282 {
1283     return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
1284                                             false);
1285 }
1286 
ValidateVertexAttribIFormat(ValidationContext * context,GLuint attribindex,GLint size,GLenum type,GLuint relativeoffset)1287 bool ValidateVertexAttribIFormat(ValidationContext *context,
1288                                  GLuint attribindex,
1289                                  GLint size,
1290                                  GLenum type,
1291                                  GLuint relativeoffset)
1292 {
1293     return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
1294 }
1295 
ValidateVertexAttribBinding(ValidationContext * context,GLuint attribIndex,GLuint bindingIndex)1296 bool ValidateVertexAttribBinding(ValidationContext *context,
1297                                  GLuint attribIndex,
1298                                  GLuint bindingIndex)
1299 {
1300     if (context->getClientVersion() < ES_3_1)
1301     {
1302         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1303         return false;
1304     }
1305 
1306     // [OpenGL ES 3.1] Section 10.3.1 page 243:
1307     // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1308     if (context->getGLState().getVertexArrayId() == 0)
1309     {
1310         context->handleError(InvalidOperation() << "Default vertex array object is bound.");
1311         return false;
1312     }
1313 
1314     const Caps &caps = context->getCaps();
1315     if (attribIndex >= caps.maxVertexAttributes)
1316     {
1317         ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
1318         return false;
1319     }
1320 
1321     if (bindingIndex >= caps.maxVertexAttribBindings)
1322     {
1323         context->handleError(InvalidValue()
1324                              << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
1325         return false;
1326     }
1327 
1328     return true;
1329 }
1330 
ValidateGetProgramResourceName(Context * context,GLuint program,GLenum programInterface,GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name)1331 bool ValidateGetProgramResourceName(Context *context,
1332                                     GLuint program,
1333                                     GLenum programInterface,
1334                                     GLuint index,
1335                                     GLsizei bufSize,
1336                                     GLsizei *length,
1337                                     GLchar *name)
1338 {
1339     if (context->getClientVersion() < ES_3_1)
1340     {
1341         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1342         return false;
1343     }
1344 
1345     Program *programObject = GetValidProgram(context, program);
1346     if (programObject == nullptr)
1347     {
1348         return false;
1349     }
1350 
1351     if (!ValidateNamedProgramInterface(programInterface))
1352     {
1353         context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1354                                            << std::uppercase << programInterface);
1355         return false;
1356     }
1357 
1358     if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1359     {
1360         context->handleError(InvalidValue() << "Invalid index: " << index);
1361         return false;
1362     }
1363 
1364     if (bufSize < 0)
1365     {
1366         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
1367         return false;
1368     }
1369 
1370     return true;
1371 }
1372 
ValidateDispatchCompute(Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)1373 bool ValidateDispatchCompute(Context *context,
1374                              GLuint numGroupsX,
1375                              GLuint numGroupsY,
1376                              GLuint numGroupsZ)
1377 {
1378     if (context->getClientVersion() < ES_3_1)
1379     {
1380         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1381         return false;
1382     }
1383 
1384     const State &state = context->getGLState();
1385     Program *program   = state.getProgram();
1386 
1387     if (program == nullptr)
1388     {
1389         context->handleError(InvalidOperation()
1390                              << "No active program object for the compute shader stage.");
1391         return false;
1392     }
1393 
1394     if (!program->isLinked() || !program->hasLinkedComputeShader())
1395     {
1396         context->handleError(
1397             InvalidOperation()
1398             << "Program has not been successfully linked, or program contains no compute shaders.");
1399         return false;
1400     }
1401 
1402     const Caps &caps = context->getCaps();
1403     if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1404     {
1405         context->handleError(
1406             InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1407                            << caps.maxComputeWorkGroupCount[0]);
1408         return false;
1409     }
1410     if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1411     {
1412         context->handleError(
1413             InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1414                            << caps.maxComputeWorkGroupCount[1]);
1415         return false;
1416     }
1417     if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1418     {
1419         context->handleError(
1420             InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1421                            << caps.maxComputeWorkGroupCount[2]);
1422         return false;
1423     }
1424 
1425     return true;
1426 }
1427 
ValidateDispatchComputeIndirect(Context * context,GLintptr indirect)1428 bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
1429 {
1430     UNIMPLEMENTED();
1431     return false;
1432 }
1433 
ValidateBindImageTexture(Context * context,GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)1434 bool ValidateBindImageTexture(Context *context,
1435                               GLuint unit,
1436                               GLuint texture,
1437                               GLint level,
1438                               GLboolean layered,
1439                               GLint layer,
1440                               GLenum access,
1441                               GLenum format)
1442 {
1443     GLuint maxImageUnits = context->getCaps().maxImageUnits;
1444     if (unit >= maxImageUnits)
1445     {
1446         context->handleError(InvalidValue()
1447                              << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1448                              << maxImageUnits);
1449         return false;
1450     }
1451 
1452     if (level < 0)
1453     {
1454         context->handleError(InvalidValue() << "level is negative.");
1455         return false;
1456     }
1457 
1458     if (layer < 0)
1459     {
1460         context->handleError(InvalidValue() << "layer is negative.");
1461         return false;
1462     }
1463 
1464     if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1465     {
1466         context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1467         return false;
1468     }
1469 
1470     switch (format)
1471     {
1472         case GL_RGBA32F:
1473         case GL_RGBA16F:
1474         case GL_R32F:
1475         case GL_RGBA32UI:
1476         case GL_RGBA16UI:
1477         case GL_RGBA8UI:
1478         case GL_R32UI:
1479         case GL_RGBA32I:
1480         case GL_RGBA16I:
1481         case GL_RGBA8I:
1482         case GL_R32I:
1483         case GL_RGBA8:
1484         case GL_RGBA8_SNORM:
1485             break;
1486         default:
1487             context->handleError(InvalidValue()
1488                                  << "format is not one of supported image unit formats.");
1489             return false;
1490     }
1491 
1492     if (texture != 0)
1493     {
1494         Texture *tex = context->getTexture(texture);
1495 
1496         if (tex == nullptr)
1497         {
1498             context->handleError(InvalidValue()
1499                                  << "texture is not the name of an existing texture object.");
1500             return false;
1501         }
1502 
1503         if (!tex->getImmutableFormat())
1504         {
1505             context->handleError(InvalidOperation()
1506                                  << "texture is not the name of an immutable texture object.");
1507             return false;
1508         }
1509     }
1510 
1511     return true;
1512 }
1513 
ValidateGetProgramResourceLocation(Context * context,GLuint program,GLenum programInterface,const GLchar * name)1514 bool ValidateGetProgramResourceLocation(Context *context,
1515                                         GLuint program,
1516                                         GLenum programInterface,
1517                                         const GLchar *name)
1518 {
1519     if (context->getClientVersion() < ES_3_1)
1520     {
1521         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1522         return false;
1523     }
1524 
1525     Program *programObject = GetValidProgram(context, program);
1526     if (programObject == nullptr)
1527     {
1528         return false;
1529     }
1530 
1531     if (!programObject->isLinked())
1532     {
1533         context->handleError(InvalidOperation() << "Program is not successfully linked.");
1534         return false;
1535     }
1536 
1537     if (!ValidateLocationProgramInterface(programInterface))
1538     {
1539         context->handleError(InvalidEnum() << "Invalid program interface.");
1540         return false;
1541     }
1542     return true;
1543 }
1544 
ValidateGetProgramResourceiv(Context * context,GLuint program,GLenum programInterface,GLuint index,GLsizei propCount,const GLenum * props,GLsizei bufSize,GLsizei * length,GLint * params)1545 bool ValidateGetProgramResourceiv(Context *context,
1546                                   GLuint program,
1547                                   GLenum programInterface,
1548                                   GLuint index,
1549                                   GLsizei propCount,
1550                                   const GLenum *props,
1551                                   GLsizei bufSize,
1552                                   GLsizei *length,
1553                                   GLint *params)
1554 {
1555     if (context->getClientVersion() < ES_3_1)
1556     {
1557         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1558         return false;
1559     }
1560 
1561     Program *programObject = GetValidProgram(context, program);
1562     if (programObject == nullptr)
1563     {
1564         return false;
1565     }
1566     if (!ValidateProgramInterface(programInterface))
1567     {
1568         context->handleError(InvalidEnum() << "Invalid program interface.");
1569         return false;
1570     }
1571     if (propCount <= 0)
1572     {
1573         context->handleError(InvalidValue() << "Invalid propCount.");
1574         return false;
1575     }
1576     if (bufSize < 0)
1577     {
1578         context->handleError(InvalidValue() << "Invalid bufSize.");
1579         return false;
1580     }
1581     if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1582     {
1583         context->handleError(InvalidValue() << "Invalid index: " << index);
1584         return false;
1585     }
1586     for (GLsizei i = 0; i < propCount; i++)
1587     {
1588         if (!ValidateProgramResourceProperty(props[i]))
1589         {
1590             context->handleError(InvalidEnum() << "Invalid prop.");
1591             return false;
1592         }
1593         if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1594         {
1595             context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1596             return false;
1597         }
1598     }
1599     return true;
1600 }
1601 
ValidateGetProgramInterfaceiv(Context * context,GLuint program,GLenum programInterface,GLenum pname,GLint * params)1602 bool ValidateGetProgramInterfaceiv(Context *context,
1603                                    GLuint program,
1604                                    GLenum programInterface,
1605                                    GLenum pname,
1606                                    GLint *params)
1607 {
1608     if (context->getClientVersion() < ES_3_1)
1609     {
1610         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1611         return false;
1612     }
1613 
1614     Program *programObject = GetValidProgram(context, program);
1615     if (programObject == nullptr)
1616     {
1617         return false;
1618     }
1619 
1620     if (!ValidateProgramInterface(programInterface))
1621     {
1622         context->handleError(InvalidEnum() << "Invalid program interface.");
1623         return false;
1624     }
1625 
1626     switch (pname)
1627     {
1628         case GL_ACTIVE_RESOURCES:
1629         case GL_MAX_NAME_LENGTH:
1630         case GL_MAX_NUM_ACTIVE_VARIABLES:
1631             break;
1632 
1633         default:
1634             context->handleError(InvalidEnum() << "Unknown property of program interface.");
1635             return false;
1636     }
1637 
1638     if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1639     {
1640         context->handleError(InvalidOperation()
1641                              << "Active atomic counter resources are not assigned name strings.");
1642         return false;
1643     }
1644 
1645     if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1646     {
1647         switch (programInterface)
1648         {
1649             case GL_ATOMIC_COUNTER_BUFFER:
1650             case GL_SHADER_STORAGE_BLOCK:
1651             case GL_UNIFORM_BLOCK:
1652                 break;
1653 
1654             default:
1655                 context->handleError(
1656                     InvalidOperation()
1657                     << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1658                 return false;
1659         }
1660     }
1661 
1662     return true;
1663 }
1664 
ValidateGenOrDeleteES31(Context * context,GLint n)1665 static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1666 {
1667     if (context->getClientVersion() < ES_3_1)
1668     {
1669         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1670         return false;
1671     }
1672 
1673     return ValidateGenOrDelete(context, n);
1674 }
1675 
ValidateGenProgramPipelines(Context * context,GLint n,GLuint *)1676 bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1677 {
1678     return ValidateGenOrDeleteES31(context, n);
1679 }
1680 
ValidateDeleteProgramPipelines(Context * context,GLint n,const GLuint *)1681 bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1682 {
1683     return ValidateGenOrDeleteES31(context, n);
1684 }
1685 
ValidateBindProgramPipeline(Context * context,GLuint pipeline)1686 bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1687 {
1688     if (context->getClientVersion() < ES_3_1)
1689     {
1690         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1691         return false;
1692     }
1693 
1694     if (!context->isProgramPipelineGenerated(pipeline))
1695     {
1696         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1697         return false;
1698     }
1699 
1700     return true;
1701 }
1702 
ValidateIsProgramPipeline(Context * context,GLuint pipeline)1703 bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1704 {
1705     if (context->getClientVersion() < ES_3_1)
1706     {
1707         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1708         return false;
1709     }
1710 
1711     return true;
1712 }
1713 
ValidateUseProgramStages(Context * context,GLuint pipeline,GLbitfield stages,GLuint program)1714 bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
1715 {
1716     UNIMPLEMENTED();
1717     return false;
1718 }
1719 
ValidateActiveShaderProgram(Context * context,GLuint pipeline,GLuint program)1720 bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
1721 {
1722     UNIMPLEMENTED();
1723     return false;
1724 }
1725 
ValidateCreateShaderProgramv(Context * context,GLenum type,GLsizei count,const GLchar * const * strings)1726 bool ValidateCreateShaderProgramv(Context *context,
1727                                   GLenum type,
1728                                   GLsizei count,
1729                                   const GLchar *const *strings)
1730 {
1731     UNIMPLEMENTED();
1732     return false;
1733 }
1734 
ValidateGetProgramPipelineiv(Context * context,GLuint pipeline,GLenum pname,GLint * params)1735 bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
1736 {
1737     UNIMPLEMENTED();
1738     return false;
1739 }
1740 
ValidateValidateProgramPipeline(Context * context,GLuint pipeline)1741 bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
1742 {
1743     UNIMPLEMENTED();
1744     return false;
1745 }
1746 
ValidateGetProgramPipelineInfoLog(Context * context,GLuint pipeline,GLsizei bufSize,GLsizei * length,GLchar * infoLog)1747 bool ValidateGetProgramPipelineInfoLog(Context *context,
1748                                        GLuint pipeline,
1749                                        GLsizei bufSize,
1750                                        GLsizei *length,
1751                                        GLchar *infoLog)
1752 {
1753     UNIMPLEMENTED();
1754     return false;
1755 }
1756 
ValidateMemoryBarrier(Context * context,GLbitfield barriers)1757 bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
1758 {
1759     UNIMPLEMENTED();
1760     return false;
1761 }
1762 
ValidateMemoryBarrierByRegion(Context * context,GLbitfield barriers)1763 bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
1764 {
1765     UNIMPLEMENTED();
1766     return false;
1767 }
1768 
ValidateSampleMaski(Context * context,GLuint maskNumber,GLbitfield mask)1769 bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
1770 {
1771     if (context->getClientVersion() < ES_3_1)
1772     {
1773         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1774         return false;
1775     }
1776 
1777     if (maskNumber >= context->getCaps().maxSampleMaskWords)
1778     {
1779         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1780         return false;
1781     }
1782 
1783     return true;
1784 }
1785 
1786 }  // namespace gl
1787