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