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