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