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