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