1 //
2 // Copyright 2013 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 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
9 #ifndef LIBANGLE_VALIDATION_ES_H_
10 #define LIBANGLE_VALIDATION_ES_H_
11
12 #include "common/PackedEnums.h"
13 #include "common/mathutil.h"
14 #include "common/utilities.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/ErrorStrings.h"
17 #include "libANGLE/Framebuffer.h"
18 #include "libANGLE/VertexArray.h"
19
20 #include <GLES2/gl2.h>
21 #include <GLES3/gl3.h>
22 #include <GLES3/gl31.h>
23
24 namespace egl
25 {
26 class Display;
27 class Image;
28 } // namespace egl
29
30 namespace gl
31 {
32 class Context;
33 struct Format;
34 class Framebuffer;
35 struct LinkedUniform;
36 class Program;
37 class Shader;
38
39 #define ANGLE_VALIDATION_ERROR(errorCode, message) \
40 context->getMutableErrorSetForValidation()->validationError(entryPoint, errorCode, message)
41 #define ANGLE_VALIDATION_ERRORF(errorCode, ...) \
42 context->getMutableErrorSetForValidation()->validationErrorF(entryPoint, errorCode, __VA_ARGS__)
43
44 void SetRobustLengthParam(const GLsizei *length, GLsizei value);
45 bool ValidTextureTarget(const Context *context, TextureType type);
46 bool ValidTexture2DTarget(const Context *context, TextureType type);
47 bool ValidTexture3DTarget(const Context *context, TextureType target);
48 bool ValidTextureExternalTarget(const Context *context, TextureType target);
49 bool ValidTextureExternalTarget(const Context *context, TextureTarget target);
50 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target);
51 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target);
52 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type);
53 bool ValidFramebufferTarget(const Context *context, GLenum target);
54 bool ValidMipLevel(const Context *context, TextureType type, GLint level);
55 bool ValidImageSizeParameters(const Context *context,
56 angle::EntryPoint entryPoint,
57 TextureType target,
58 GLint level,
59 GLsizei width,
60 GLsizei height,
61 GLsizei depth,
62 bool isSubImage);
63 bool ValidCompressedImageSize(const Context *context,
64 GLenum internalFormat,
65 GLint level,
66 GLsizei width,
67 GLsizei height,
68 GLsizei depth);
69 bool ValidCompressedSubImageSize(const Context *context,
70 GLenum internalFormat,
71 GLint xoffset,
72 GLint yoffset,
73 GLint zoffset,
74 GLsizei width,
75 GLsizei height,
76 GLsizei depth,
77 size_t textureWidth,
78 size_t textureHeight,
79 size_t textureDepth);
80 bool ValidImageDataSize(const Context *context,
81 angle::EntryPoint entryPoint,
82 TextureType texType,
83 GLsizei width,
84 GLsizei height,
85 GLsizei depth,
86 GLenum format,
87 GLenum type,
88 const void *pixels,
89 GLsizei imageSize);
90
91 bool ValidQueryType(const Context *context, QueryType queryType);
92
93 bool ValidateWebGLVertexAttribPointer(const Context *context,
94 angle::EntryPoint entryPoint,
95 VertexAttribType type,
96 GLboolean normalized,
97 GLsizei stride,
98 const void *ptr,
99 bool pureInteger);
100
101 // Returns valid program if id is a valid program name
102 // Errors INVALID_OPERATION if valid shader is given and returns NULL
103 // Errors INVALID_VALUE otherwise and returns NULL
104 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id);
105
106 // Returns valid shader if id is a valid shader name
107 // Errors INVALID_OPERATION if valid program is given and returns NULL
108 // Errors INVALID_VALUE otherwise and returns NULL
109 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id);
110
111 bool ValidateAttachmentTarget(const Context *context,
112 angle::EntryPoint entryPoint,
113 GLenum attachment);
114
115 bool ValidateBlitFramebufferParameters(const Context *context,
116 angle::EntryPoint entryPoint,
117 GLint srcX0,
118 GLint srcY0,
119 GLint srcX1,
120 GLint srcY1,
121 GLint dstX0,
122 GLint dstY0,
123 GLint dstX1,
124 GLint dstY1,
125 GLbitfield mask,
126 GLenum filter);
127
128 bool ValidateBindFramebufferBase(const Context *context,
129 angle::EntryPoint entryPoint,
130 GLenum target,
131 FramebufferID framebuffer);
132 bool ValidateBindRenderbufferBase(const Context *context,
133 angle::EntryPoint entryPoint,
134 GLenum target,
135 RenderbufferID renderbuffer);
136 bool ValidateFramebufferParameteriBase(const Context *context,
137 angle::EntryPoint entryPoint,
138 GLenum target,
139 GLenum pname,
140 GLint param);
141 bool ValidateFramebufferRenderbufferBase(const Context *context,
142 angle::EntryPoint entryPoint,
143 GLenum target,
144 GLenum attachment,
145 GLenum renderbuffertarget,
146 RenderbufferID renderbuffer);
147 bool ValidateFramebufferTextureBase(const Context *context,
148 angle::EntryPoint entryPoint,
149 GLenum target,
150 GLenum attachment,
151 TextureID texture,
152 GLint level);
153 bool ValidateGenerateMipmapBase(const Context *context,
154 angle::EntryPoint entryPoint,
155 TextureType target);
156
157 bool ValidateRenderbufferStorageParametersBase(const Context *context,
158 angle::EntryPoint entryPoint,
159 GLenum target,
160 GLsizei samples,
161 GLenum internalformat,
162 GLsizei width,
163 GLsizei height);
164
165 bool ValidatePixelPack(const Context *context,
166 angle::EntryPoint entryPoint,
167 GLenum format,
168 GLenum type,
169 GLint x,
170 GLint y,
171 GLsizei width,
172 GLsizei height,
173 GLsizei bufSize,
174 GLsizei *length,
175 const void *pixels);
176
177 bool ValidateReadPixelsBase(const Context *context,
178 angle::EntryPoint entryPoint,
179 GLint x,
180 GLint y,
181 GLsizei width,
182 GLsizei height,
183 GLenum format,
184 GLenum type,
185 GLsizei bufSize,
186 GLsizei *length,
187 GLsizei *columns,
188 GLsizei *rows,
189 const void *pixels);
190 bool ValidateReadPixelsRobustANGLE(const Context *context,
191 angle::EntryPoint entryPoint,
192 GLint x,
193 GLint y,
194 GLsizei width,
195 GLsizei height,
196 GLenum format,
197 GLenum type,
198 GLsizei bufSize,
199 const GLsizei *length,
200 const GLsizei *columns,
201 const GLsizei *rows,
202 const void *pixels);
203 bool ValidateReadnPixelsEXT(const Context *context,
204 angle::EntryPoint entryPoint,
205 GLint x,
206 GLint y,
207 GLsizei width,
208 GLsizei height,
209 GLenum format,
210 GLenum type,
211 GLsizei bufSize,
212 const void *pixels);
213 bool ValidateReadnPixelsRobustANGLE(const Context *context,
214 angle::EntryPoint entryPoint,
215 GLint x,
216 GLint y,
217 GLsizei width,
218 GLsizei height,
219 GLenum format,
220 GLenum type,
221 GLsizei bufSize,
222 const GLsizei *length,
223 const GLsizei *columns,
224 const GLsizei *rows,
225 const void *data);
226
227 bool ValidateGenQueriesEXT(const Context *context,
228 angle::EntryPoint entryPoint,
229 GLsizei n,
230 const QueryID *ids);
231 bool ValidateDeleteQueriesEXT(const Context *context,
232 angle::EntryPoint entryPoint,
233 GLsizei n,
234 const QueryID *ids);
235 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id);
236 bool ValidateBeginQueryBase(const Context *context,
237 angle::EntryPoint entryPoint,
238 QueryType target,
239 QueryID id);
240 bool ValidateBeginQueryEXT(const Context *context,
241 angle::EntryPoint entryPoint,
242 QueryType target,
243 QueryID id);
244 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target);
245 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target);
246 bool ValidateQueryCounterEXT(const Context *context,
247 angle::EntryPoint entryPoint,
248 QueryID id,
249 QueryType target);
250 bool ValidateGetQueryivBase(const Context *context,
251 angle::EntryPoint entryPoint,
252 QueryType target,
253 GLenum pname,
254 GLsizei *numParams);
255 bool ValidateGetQueryivEXT(const Context *context,
256 angle::EntryPoint entryPoint,
257 QueryType target,
258 GLenum pname,
259 const GLint *params);
260 bool ValidateGetQueryivRobustANGLE(const Context *context,
261 angle::EntryPoint entryPoint,
262 QueryType target,
263 GLenum pname,
264 GLsizei bufSize,
265 const GLsizei *length,
266 const GLint *params);
267 bool ValidateGetQueryObjectValueBase(const Context *context,
268 angle::EntryPoint entryPoint,
269 QueryID id,
270 GLenum pname,
271 GLsizei *numParams);
272 bool ValidateGetQueryObjectivEXT(const Context *context,
273 angle::EntryPoint entryPoint,
274 QueryID id,
275 GLenum pname,
276 const GLint *params);
277 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
278 angle::EntryPoint entryPoint,
279 QueryID id,
280 GLenum pname,
281 GLsizei bufSize,
282 const GLsizei *length,
283 const GLint *params);
284 bool ValidateGetQueryObjectuivEXT(const Context *context,
285 angle::EntryPoint entryPoint,
286 QueryID id,
287 GLenum pname,
288 const GLuint *params);
289 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
290 angle::EntryPoint entryPoint,
291 QueryID id,
292 GLenum pname,
293 GLsizei bufSize,
294 const GLsizei *length,
295 const GLuint *params);
296 bool ValidateGetQueryObjecti64vEXT(const Context *context,
297 angle::EntryPoint entryPoint,
298 QueryID id,
299 GLenum pname,
300 GLint64 *params);
301 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
302 angle::EntryPoint entryPoint,
303 QueryID id,
304 GLenum pname,
305 GLsizei bufSize,
306 const GLsizei *length,
307 GLint64 *params);
308 bool ValidateGetQueryObjectui64vEXT(const Context *context,
309 angle::EntryPoint entryPoint,
310 QueryID id,
311 GLenum pname,
312 GLuint64 *params);
313 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
314 angle::EntryPoint entryPoint,
315 QueryID id,
316 GLenum pname,
317 GLsizei bufSize,
318 const GLsizei *length,
319 GLuint64 *params);
320
321 bool ValidateUniformCommonBase(const Context *context,
322 angle::EntryPoint entryPoint,
323 const Program *program,
324 UniformLocation location,
325 GLsizei count,
326 const LinkedUniform **uniformOut);
327 bool ValidateUniform1ivValue(const Context *context,
328 angle::EntryPoint entryPoint,
329 GLenum uniformType,
330 GLsizei count,
331 const GLint *value);
332
ValidateUniformValue(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,GLenum uniformType)333 ANGLE_INLINE bool ValidateUniformValue(const Context *context,
334 angle::EntryPoint entryPoint,
335 GLenum valueType,
336 GLenum uniformType)
337 {
338 // Check that the value type is compatible with uniform type.
339 // Do the cheaper test first, for a little extra speed.
340 if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
341 {
342 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kUniformSizeMismatch);
343 return false;
344 }
345 return true;
346 }
347
348 bool ValidateUniformMatrixValue(const Context *context,
349 angle::EntryPoint entryPoint,
350 GLenum valueType,
351 GLenum uniformType);
352 bool ValidateUniform(const Context *context,
353 angle::EntryPoint entryPoint,
354 GLenum uniformType,
355 UniformLocation location,
356 GLsizei count);
357 bool ValidateUniformMatrix(const Context *context,
358 angle::EntryPoint entryPoint,
359 GLenum matrixType,
360 UniformLocation location,
361 GLsizei count,
362 GLboolean transpose);
363 bool ValidateGetBooleanvRobustANGLE(const Context *context,
364 angle::EntryPoint entryPoint,
365 GLenum pname,
366 GLsizei bufSize,
367 const GLsizei *length,
368 const GLboolean *params);
369 bool ValidateGetFloatvRobustANGLE(const Context *context,
370 angle::EntryPoint entryPoint,
371 GLenum pname,
372 GLsizei bufSize,
373 const GLsizei *length,
374 const GLfloat *params);
375 bool ValidateStateQuery(const Context *context,
376 angle::EntryPoint entryPoint,
377 GLenum pname,
378 GLenum *nativeType,
379 unsigned int *numParams);
380 bool ValidateGetIntegervRobustANGLE(const Context *context,
381 angle::EntryPoint entryPoint,
382 GLenum pname,
383 GLsizei bufSize,
384 const GLsizei *length,
385 const GLint *data);
386 bool ValidateGetInteger64vRobustANGLE(const Context *context,
387 angle::EntryPoint entryPoint,
388 GLenum pname,
389 GLsizei bufSize,
390 const GLsizei *length,
391 GLint64 *data);
392 bool ValidateRobustStateQuery(const Context *context,
393 angle::EntryPoint entryPoint,
394 GLenum pname,
395 GLsizei bufSize,
396 GLenum *nativeType,
397 unsigned int *numParams);
398
399 bool ValidateCopyImageSubDataBase(const Context *context,
400 angle::EntryPoint entryPoint,
401 GLuint srcName,
402 GLenum srcTarget,
403 GLint srcLevel,
404 GLint srcX,
405 GLint srcY,
406 GLint srcZ,
407 GLuint dstName,
408 GLenum dstTarget,
409 GLint dstLevel,
410 GLint dstX,
411 GLint dstY,
412 GLint dstZ,
413 GLsizei srcWidth,
414 GLsizei srcHeight,
415 GLsizei srcDepth);
416
417 bool ValidateCopyTexImageParametersBase(const Context *context,
418 angle::EntryPoint entryPoint,
419 TextureTarget target,
420 GLint level,
421 GLenum internalformat,
422 bool isSubImage,
423 GLint xoffset,
424 GLint yoffset,
425 GLint zoffset,
426 GLint x,
427 GLint y,
428 GLsizei width,
429 GLsizei height,
430 GLint border,
431 Format *textureFormatOut);
432
433 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode);
434 const char *ValidateDrawElementsStates(const Context *context);
435
ValidateDrawBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode)436 ANGLE_INLINE bool ValidateDrawBase(const Context *context,
437 angle::EntryPoint entryPoint,
438 PrimitiveMode mode)
439 {
440 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesErrorString(
441 context, &context->getPrivateStateCache());
442 if (drawStatesError)
443 {
444 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
445 GLenum errorCode = context->getStateCache().getBasicDrawElementsErrorCode();
446 ANGLE_VALIDATION_ERROR(errorCode, errorMessage);
447 return false;
448 }
449
450 if (!context->getStateCache().isValidDrawMode(mode))
451 {
452 RecordDrawModeError(context, entryPoint, mode);
453 return false;
454 }
455
456 return true;
457 }
458
459 bool ValidateDrawArraysInstancedBase(const Context *context,
460 angle::EntryPoint entryPoint,
461 PrimitiveMode mode,
462 GLint first,
463 GLsizei count,
464 GLsizei primcount,
465 GLuint baseinstance);
466 bool ValidateDrawArraysInstancedANGLE(const Context *context,
467 angle::EntryPoint entryPoint,
468 PrimitiveMode mode,
469 GLint first,
470 GLsizei count,
471 GLsizei primcount);
472 bool ValidateDrawArraysInstancedEXT(const Context *context,
473 angle::EntryPoint entryPoint,
474 PrimitiveMode mode,
475 GLint first,
476 GLsizei count,
477 GLsizei primcount);
478
479 bool ValidateDrawElementsInstancedBase(const Context *context,
480 angle::EntryPoint entryPoint,
481 PrimitiveMode mode,
482 GLsizei count,
483 DrawElementsType type,
484 const void *indices,
485 GLsizei primcount,
486 GLuint baseinstance);
487 bool ValidateDrawElementsInstancedANGLE(const Context *context,
488 angle::EntryPoint entryPoint,
489 PrimitiveMode mode,
490 GLsizei count,
491 DrawElementsType type,
492 const void *indices,
493 GLsizei primcount);
494 bool ValidateDrawElementsInstancedEXT(const Context *context,
495 angle::EntryPoint entryPoint,
496 PrimitiveMode mode,
497 GLsizei count,
498 DrawElementsType type,
499 const void *indices,
500 GLsizei primcount);
501
502 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint);
503
504 bool ValidateGetUniformBase(const Context *context,
505 angle::EntryPoint entryPoint,
506 ShaderProgramID program,
507 UniformLocation location);
508 bool ValidateSizedGetUniform(const Context *context,
509 angle::EntryPoint entryPoint,
510 ShaderProgramID program,
511 UniformLocation location,
512 GLsizei bufSize,
513 GLsizei *length);
514 bool ValidateGetnUniformfvEXT(const Context *context,
515 angle::EntryPoint entryPoint,
516 ShaderProgramID program,
517 UniformLocation location,
518 GLsizei bufSize,
519 const GLfloat *params);
520 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
521 angle::EntryPoint entryPoint,
522 ShaderProgramID program,
523 UniformLocation location,
524 GLsizei bufSize,
525 const GLsizei *length,
526 const GLfloat *params);
527 bool ValidateGetnUniformivEXT(const Context *context,
528 angle::EntryPoint entryPoint,
529 ShaderProgramID program,
530 UniformLocation location,
531 GLsizei bufSize,
532 const GLint *params);
533 bool ValidateGetnUniformivRobustANGLE(const Context *context,
534 angle::EntryPoint entryPoint,
535 ShaderProgramID program,
536 UniformLocation location,
537 GLsizei bufSize,
538 const GLsizei *length,
539 const GLint *params);
540 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
541 angle::EntryPoint entryPoint,
542 ShaderProgramID program,
543 UniformLocation location,
544 GLsizei bufSize,
545 const GLsizei *length,
546 const GLuint *params);
547 bool ValidateGetUniformfvRobustANGLE(const Context *context,
548 angle::EntryPoint entryPoint,
549 ShaderProgramID program,
550 UniformLocation location,
551 GLsizei bufSize,
552 const GLsizei *length,
553 const GLfloat *params);
554 bool ValidateGetUniformivRobustANGLE(const Context *context,
555 angle::EntryPoint entryPoint,
556 ShaderProgramID program,
557 UniformLocation location,
558 GLsizei bufSize,
559 const GLsizei *length,
560 const GLint *params);
561 bool ValidateGetUniformuivRobustANGLE(const Context *context,
562 angle::EntryPoint entryPoint,
563 ShaderProgramID program,
564 UniformLocation location,
565 GLsizei bufSize,
566 const GLsizei *length,
567 const GLuint *params);
568
569 bool ValidateDiscardFramebufferBase(const Context *context,
570 angle::EntryPoint entryPoint,
571 GLenum target,
572 GLsizei numAttachments,
573 const GLenum *attachments,
574 bool defaultFramebuffer);
575
576 bool ValidateInsertEventMarkerEXT(const Context *context,
577 angle::EntryPoint entryPoint,
578 GLsizei length,
579 const char *marker);
580 bool ValidatePushGroupMarkerEXT(const Context *context,
581 angle::EntryPoint entryPoint,
582 GLsizei length,
583 const char *marker);
584 bool ValidateEGLImageObject(const Context *context,
585 angle::EntryPoint entryPoint,
586 TextureType type,
587 egl::ImageID image);
588 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
589 angle::EntryPoint entryPoint,
590 TextureType type,
591 egl::ImageID image);
592 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
593 angle::EntryPoint entryPoint,
594 GLenum target,
595 egl::ImageID image);
596
597 bool ValidateProgramBinaryBase(const Context *context,
598 angle::EntryPoint entryPoint,
599 ShaderProgramID program,
600 GLenum binaryFormat,
601 const void *binary,
602 GLint length);
603 bool ValidateGetProgramBinaryBase(const Context *context,
604 angle::EntryPoint entryPoint,
605 ShaderProgramID program,
606 GLsizei bufSize,
607 const GLsizei *length,
608 const GLenum *binaryFormat,
609 const void *binary);
610
611 bool ValidateDrawBuffersBase(const Context *context,
612 angle::EntryPoint entryPoint,
613 GLsizei n,
614 const GLenum *bufs);
615
616 bool ValidateGetBufferPointervBase(const Context *context,
617 angle::EntryPoint entryPoint,
618 BufferBinding target,
619 GLenum pname,
620 GLsizei *length,
621 void *const *params);
622 bool ValidateUnmapBufferBase(const Context *context,
623 angle::EntryPoint entryPoint,
624 BufferBinding target);
625 bool ValidateMapBufferRangeBase(const Context *context,
626 angle::EntryPoint entryPoint,
627 BufferBinding target,
628 GLintptr offset,
629 GLsizeiptr length,
630 GLbitfield access);
631 bool ValidateFlushMappedBufferRangeBase(const Context *context,
632 angle::EntryPoint entryPoint,
633 BufferBinding target,
634 GLintptr offset,
635 GLsizeiptr length);
636
637 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n);
638
639 bool ValidateRobustEntryPoint(const Context *context,
640 angle::EntryPoint entryPoint,
641 GLsizei bufSize);
642 bool ValidateRobustBufferSize(const Context *context,
643 angle::EntryPoint entryPoint,
644 GLsizei bufSize,
645 GLsizei numParams);
646
647 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
648 angle::EntryPoint entryPoint,
649 GLenum target,
650 GLenum attachment,
651 GLenum pname,
652 GLsizei *numParams);
653
654 bool ValidateGetFramebufferParameterivBase(const Context *context,
655 angle::EntryPoint entryPoint,
656 GLenum target,
657 GLenum pname,
658 const GLint *params);
659
660 bool ValidateGetBufferParameterBase(const Context *context,
661 angle::EntryPoint entryPoint,
662 BufferBinding target,
663 GLenum pname,
664 bool pointerVersion,
665 GLsizei *numParams);
666
667 bool ValidateGetProgramivBase(const Context *context,
668 angle::EntryPoint entryPoint,
669 ShaderProgramID program,
670 GLenum pname,
671 GLsizei *numParams);
672
673 bool ValidateGetRenderbufferParameterivBase(const Context *context,
674 angle::EntryPoint entryPoint,
675 GLenum target,
676 GLenum pname,
677 GLsizei *length);
678
679 bool ValidateGetShaderivBase(const Context *context,
680 angle::EntryPoint entryPoint,
681 ShaderProgramID shader,
682 GLenum pname,
683 GLsizei *length);
684
685 bool ValidateGetTexParameterBase(const Context *context,
686 angle::EntryPoint entryPoint,
687 TextureType target,
688 GLenum pname,
689 GLsizei *length);
690
691 template <typename ParamType>
692 bool ValidateTexParameterBase(const Context *context,
693 angle::EntryPoint entryPoint,
694 TextureType target,
695 GLenum pname,
696 GLsizei bufSize,
697 bool vectorParams,
698 const ParamType *params);
699
700 bool ValidateGetVertexAttribBase(const Context *context,
701 angle::EntryPoint entryPoint,
702 GLuint index,
703 GLenum pname,
704 GLsizei *length,
705 bool pointer,
706 bool pureIntegerEntryPoint);
707
ValidateVertexFormat(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribTypeCase validation)708 ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
709 angle::EntryPoint entryPoint,
710 GLuint index,
711 GLint size,
712 VertexAttribTypeCase validation)
713 {
714 const Caps &caps = context->getCaps();
715 if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
716 {
717 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
718 return false;
719 }
720
721 switch (validation)
722 {
723 case VertexAttribTypeCase::Invalid:
724 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kInvalidType);
725 return false;
726 case VertexAttribTypeCase::Valid:
727 if (size < 1 || size > 4)
728 {
729 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
730 return false;
731 }
732 break;
733 case VertexAttribTypeCase::ValidSize4Only:
734 if (size != 4)
735 {
736 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize2101010);
737 return false;
738 }
739 break;
740 case VertexAttribTypeCase::ValidSize3or4:
741 if (size != 3 && size != 4)
742 {
743 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize1010102);
744 return false;
745 }
746 break;
747 }
748
749 return true;
750 }
751
752 // Note: These byte, short, and int types are all converted to float for the shader.
ValidateFloatVertexFormat(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type)753 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
754 angle::EntryPoint entryPoint,
755 GLuint index,
756 GLint size,
757 VertexAttribType type)
758 {
759 return ValidateVertexFormat(context, entryPoint, index, size,
760 context->getStateCache().getVertexAttribTypeValidation(type));
761 }
762
ValidateIntegerVertexFormat(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type)763 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
764 angle::EntryPoint entryPoint,
765 GLuint index,
766 GLint size,
767 VertexAttribType type)
768 {
769 return ValidateVertexFormat(
770 context, entryPoint, index, size,
771 context->getStateCache().getIntegerVertexAttribTypeValidation(type));
772 }
773
ValidateColorMasksForSharedExponentColorBuffers(const BlendStateExt & blendState,const Framebuffer * framebuffer)774 ANGLE_INLINE bool ValidateColorMasksForSharedExponentColorBuffers(const BlendStateExt &blendState,
775 const Framebuffer *framebuffer)
776 {
777 // Get a mask of draw buffers that have color writemasks
778 // incompatible with shared exponent color buffers.
779 // The compatible writemasks are RGBA, RGB0, 000A, 0000.
780 const BlendStateExt::ColorMaskStorage::Type rgbEnabledBits =
781 blendState.expandColorMaskValue(true, true, true, false);
782 const BlendStateExt::ColorMaskStorage::Type colorMaskNoAlphaBits =
783 blendState.getColorMaskBits() & rgbEnabledBits;
784 const DrawBufferMask incompatibleDiffMask =
785 BlendStateExt::ColorMaskStorage::GetDiffMask(colorMaskNoAlphaBits, 0) &
786 BlendStateExt::ColorMaskStorage::GetDiffMask(colorMaskNoAlphaBits, rgbEnabledBits);
787
788 const DrawBufferMask sharedExponentBufferMask =
789 framebuffer->getActiveSharedExponentColorAttachmentDrawBufferMask();
790 return (sharedExponentBufferMask & incompatibleDiffMask).none();
791 }
792
793 bool ValidateRobustCompressedTexImageBase(const Context *context,
794 angle::EntryPoint entryPoint,
795 GLsizei imageSize,
796 GLsizei dataSize);
797
798 bool ValidateVertexAttribIndex(const PrivateState &state,
799 ErrorSet *errors,
800 angle::EntryPoint entryPoint,
801 GLuint index);
802
803 bool ValidateGetActiveUniformBlockivBase(const Context *context,
804 angle::EntryPoint entryPoint,
805 ShaderProgramID program,
806 UniformBlockIndex uniformBlockIndex,
807 GLenum pname,
808 GLsizei *length);
809
810 bool ValidateGetSamplerParameterBase(const Context *context,
811 angle::EntryPoint entryPoint,
812 SamplerID sampler,
813 GLenum pname,
814 GLsizei *length);
815
816 template <typename ParamType>
817 bool ValidateSamplerParameterBase(const Context *context,
818 angle::EntryPoint entryPoint,
819 SamplerID sampler,
820 GLenum pname,
821 GLsizei bufSize,
822 bool vectorParams,
823 const ParamType *params);
824
825 bool ValidateGetInternalFormativBase(const Context *context,
826 angle::EntryPoint entryPoint,
827 GLenum target,
828 GLenum internalformat,
829 GLenum pname,
830 GLsizei bufSize,
831 GLsizei *numParams);
832
833 bool ValidateFramebufferNotMultisampled(const Context *context,
834 angle::EntryPoint entryPoint,
835 const Framebuffer *framebuffer,
836 bool checkReadBufferResourceSamples);
837
838 bool ValidateMultitextureUnit(const PrivateState &state,
839 ErrorSet *errors,
840 angle::EntryPoint entryPoint,
841 GLenum texture);
842
843 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
844 angle::EntryPoint entryPoint,
845 PrimitiveMode transformFeedbackPrimitiveMode,
846 PrimitiveMode renderPrimitiveMode);
847
848 // Common validation for 2D and 3D variants of TexStorage*Multisample.
849 bool ValidateTexStorageMultisample(const Context *context,
850 angle::EntryPoint entryPoint,
851 TextureType target,
852 GLsizei samples,
853 GLint internalFormat,
854 GLsizei width,
855 GLsizei height);
856
857 bool ValidateTexStorage2DMultisampleBase(const Context *context,
858 angle::EntryPoint entryPoint,
859 TextureType target,
860 GLsizei samples,
861 GLint internalFormat,
862 GLsizei width,
863 GLsizei height);
864
865 bool ValidateTexStorage3DMultisampleBase(const Context *context,
866 angle::EntryPoint entryPoint,
867 TextureType target,
868 GLsizei samples,
869 GLenum internalformat,
870 GLsizei width,
871 GLsizei height,
872 GLsizei depth);
873
874 bool ValidateGetTexLevelParameterBase(const Context *context,
875 angle::EntryPoint entryPoint,
876 TextureTarget target,
877 GLint level,
878 GLenum pname,
879 GLsizei *length);
880
881 bool ValidateMapBufferBase(const Context *context,
882 angle::EntryPoint entryPoint,
883 BufferBinding target);
884 bool ValidateIndexedStateQuery(const Context *context,
885 angle::EntryPoint entryPoint,
886 GLenum pname,
887 GLuint index,
888 GLsizei *length);
889 bool ValidateES3TexImage2DParameters(const Context *context,
890 angle::EntryPoint entryPoint,
891 TextureTarget target,
892 GLint level,
893 GLenum internalformat,
894 bool isCompressed,
895 bool isSubImage,
896 GLint xoffset,
897 GLint yoffset,
898 GLint zoffset,
899 GLsizei width,
900 GLsizei height,
901 GLsizei depth,
902 GLint border,
903 GLenum format,
904 GLenum type,
905 GLsizei imageSize,
906 const void *pixels);
907 bool ValidateES3CopyTexImage2DParameters(const Context *context,
908 angle::EntryPoint entryPoint,
909 TextureTarget target,
910 GLint level,
911 GLenum internalformat,
912 bool isSubImage,
913 GLint xoffset,
914 GLint yoffset,
915 GLint zoffset,
916 GLint x,
917 GLint y,
918 GLsizei width,
919 GLsizei height,
920 GLint border);
921 bool ValidateES3TexStorageParametersBase(const Context *context,
922 angle::EntryPoint entryPoint,
923 TextureType target,
924 GLsizei levels,
925 GLenum internalformat,
926 GLsizei width,
927 GLsizei height,
928 GLsizei depth);
929 bool ValidateES3TexStorage2DParameters(const Context *context,
930 angle::EntryPoint entryPoint,
931 TextureType target,
932 GLsizei levels,
933 GLenum internalformat,
934 GLsizei width,
935 GLsizei height,
936 GLsizei depth);
937 bool ValidateES3TexStorage3DParameters(const Context *context,
938 angle::EntryPoint entryPoint,
939 TextureType target,
940 GLsizei levels,
941 GLenum internalformat,
942 GLsizei width,
943 GLsizei height,
944 GLsizei depth);
945
946 bool ValidateGetMultisamplefvBase(const Context *context,
947 angle::EntryPoint entryPoint,
948 GLenum pname,
949 GLuint index,
950 const GLfloat *val);
951 bool ValidateSampleMaskiBase(const PrivateState &state,
952 ErrorSet *errors,
953 angle::EntryPoint entryPoint,
954 GLuint maskNumber,
955 GLbitfield mask);
956
957 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
958 const ProgramExecutable *programExecutable);
959
960 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
961 // implementation format info for incomplete framebuffers. It seems like these queries are
962 // incongruent with the other errors.
963 // Inlined for speed.
964 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,angle::EntryPoint entryPoint,const Framebuffer * framebuffer)965 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
966 angle::EntryPoint entryPoint,
967 const Framebuffer *framebuffer)
968 {
969 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
970 if (!framebufferStatus.isComplete())
971 {
972 ASSERT(framebufferStatus.reason != nullptr);
973 ANGLE_VALIDATION_ERROR(ErrorCode, framebufferStatus.reason);
974 return false;
975 }
976
977 return true;
978 }
979
980 const char *ValidateProgramPipelineDrawStates(const State &state,
981 const Extensions &extensions,
982 ProgramPipeline *programPipeline);
983 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
984 const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode);
985 const char *ValidateProgramPipeline(const Context *context);
986
987 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint);
988
ValidateDrawAttribs(const Context * context,angle::EntryPoint entryPoint,int64_t maxVertex)989 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context,
990 angle::EntryPoint entryPoint,
991 int64_t maxVertex)
992 {
993 // For non-instanced attributes, the maximum vertex must be accessible in the attribute buffers.
994 // For instanced attributes, in non-instanced draw calls only attribute 0 is accessed. In
995 // instanced draw calls, the instance limit is checked in ValidateDrawInstancedAttribs.
996 if (maxVertex >= context->getStateCache().getNonInstancedVertexElementLimit() ||
997 context->getStateCache().getInstancedVertexElementLimit() < 1)
998 {
999 RecordDrawAttribsError(context, entryPoint);
1000 return false;
1001 }
1002
1003 return true;
1004 }
1005
ValidateDrawArraysAttribs(const Context * context,angle::EntryPoint entryPoint,GLint first,GLsizei count)1006 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context,
1007 angle::EntryPoint entryPoint,
1008 GLint first,
1009 GLsizei count)
1010 {
1011 if (!context->isBufferAccessValidationEnabled())
1012 {
1013 return true;
1014 }
1015
1016 // Check the computation of maxVertex doesn't overflow.
1017 // - first < 0 has been checked as an error condition.
1018 // - if count <= 0, skip validating no-op draw calls.
1019 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
1020 ASSERT(first >= 0);
1021 ASSERT(count > 0);
1022 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
1023 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
1024 {
1025 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1026 return false;
1027 }
1028
1029 return ValidateDrawAttribs(context, entryPoint, maxVertex);
1030 }
1031
ValidateDrawInstancedAttribs(const Context * context,angle::EntryPoint entryPoint,GLint primcount,GLuint baseinstance)1032 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context,
1033 angle::EntryPoint entryPoint,
1034 GLint primcount,
1035 GLuint baseinstance)
1036 {
1037 if (!context->isBufferAccessValidationEnabled())
1038 {
1039 return true;
1040 }
1041
1042 // Validate that the buffers bound for the attributes can hold enough vertices for this
1043 // instanced draw. For attributes with a divisor of 0, ValidateDrawAttribs already checks this.
1044 // Thus, the following only checks attributes with a non-zero divisor (i.e. "instanced").
1045 const GLint64 limit = context->getStateCache().getInstancedVertexElementLimit();
1046 if (baseinstance >= limit || primcount > limit - baseinstance)
1047 {
1048 RecordDrawAttribsError(context, entryPoint);
1049 return false;
1050 }
1051
1052 return true;
1053 }
1054
ValidateDrawArraysCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)1055 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
1056 angle::EntryPoint entryPoint,
1057 PrimitiveMode mode,
1058 GLint first,
1059 GLsizei count,
1060 GLsizei primcount)
1061 {
1062 if (first < 0)
1063 {
1064 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeStart);
1065 return false;
1066 }
1067
1068 if (count <= 0)
1069 {
1070 if (count < 0)
1071 {
1072 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1073 return false;
1074 }
1075
1076 // Early exit.
1077 return ValidateDrawBase(context, entryPoint, mode);
1078 }
1079
1080 if (primcount <= 0)
1081 {
1082 if (primcount < 0)
1083 {
1084 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1085 return false;
1086 }
1087 // Early exit.
1088 return ValidateDrawBase(context, entryPoint, mode);
1089 }
1090
1091 if (!ValidateDrawBase(context, entryPoint, mode))
1092 {
1093 return false;
1094 }
1095
1096 if (context->getStateCache().isTransformFeedbackActiveUnpaused() &&
1097 !context->supportsGeometryOrTesselation())
1098 {
1099 const State &state = context->getState();
1100 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
1101 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
1102 {
1103 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
1104 return false;
1105 }
1106 }
1107
1108 return ValidateDrawArraysAttribs(context, entryPoint, first, count);
1109 }
1110
ValidateDrawElementsBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,DrawElementsType type)1111 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
1112 angle::EntryPoint entryPoint,
1113 PrimitiveMode mode,
1114 DrawElementsType type)
1115 {
1116 if (!context->getStateCache().isValidDrawElementsType(type))
1117 {
1118 if (type == DrawElementsType::UnsignedInt)
1119 {
1120 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
1121 return false;
1122 }
1123
1124 ASSERT(type == DrawElementsType::InvalidEnum);
1125 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, err::kEnumInvalid);
1126 return false;
1127 }
1128
1129 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
1130 if (drawElementsError)
1131 {
1132 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
1133 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
1134 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, errorMessage);
1135 return false;
1136 }
1137
1138 // Note that we are missing overflow checks for active transform feedback buffers.
1139 return true;
1140 }
1141
ValidateDrawElementsCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)1142 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
1143 angle::EntryPoint entryPoint,
1144 PrimitiveMode mode,
1145 GLsizei count,
1146 DrawElementsType type,
1147 const void *indices,
1148 GLsizei primcount)
1149 {
1150 if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
1151 {
1152 return false;
1153 }
1154
1155 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
1156
1157 if (context->isWebGL())
1158 {
1159 GLuint typeBytes = GetDrawElementsTypeSize(type);
1160
1161 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
1162 {
1163 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
1164 // The offset arguments to drawElements and [...], must be a multiple of the size of the
1165 // data type passed to the call, or an INVALID_OPERATION error is generated.
1166 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
1167 return false;
1168 }
1169
1170 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
1171 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
1172 // error is generated.
1173 if (reinterpret_cast<intptr_t>(indices) < 0)
1174 {
1175 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeOffset);
1176 return false;
1177 }
1178 }
1179
1180 if (count <= 0)
1181 {
1182 if (count < 0)
1183 {
1184 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1185 return false;
1186 }
1187
1188 // Early exit.
1189 return ValidateDrawBase(context, entryPoint, mode);
1190 }
1191
1192 if (!ValidateDrawBase(context, entryPoint, mode))
1193 {
1194 return false;
1195 }
1196
1197 const State &state = context->getState();
1198 const VertexArray *vao = state.getVertexArray();
1199 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1200
1201 if (!elementArrayBuffer)
1202 {
1203 if (!indices)
1204 {
1205 // This is an application error that would normally result in a crash, but we catch
1206 // it and return an error
1207 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
1208 return false;
1209 }
1210 }
1211 else
1212 {
1213 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
1214 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
1215 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
1216 constexpr uint64_t kMaxTypeSize = 8;
1217 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
1218 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
1219 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
1220
1221 uint64_t elementCount = static_cast<uint64_t>(count);
1222 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
1223
1224 // Doing the multiplication here is overflow-safe
1225 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
1226
1227 // The offset can be any value, check for overflows
1228 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
1229 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
1230 if (elementDataSizeWithOffset < elementDataSizeNoOffset)
1231 {
1232 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1233 return false;
1234 }
1235
1236 // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064
1237 if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) &&
1238 (primcount > 0))
1239 {
1240 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
1241 return false;
1242 }
1243 }
1244
1245 if (context->isBufferAccessValidationEnabled() && primcount > 0)
1246 {
1247 // Use the parameter buffer to retrieve and cache the index range.
1248 // TODO: this calculation should take basevertex into account for
1249 // glDrawElementsInstancedBaseVertexBaseInstanceEXT. http://anglebug.com/41481166
1250 IndexRange indexRange{IndexRange::Undefined()};
1251 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
1252
1253 // If we use an index greater than our maximum supported index range, return an error.
1254 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1255 // always return an error if possible here.
1256 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1257 {
1258 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1259 return false;
1260 }
1261
1262 if (!ValidateDrawAttribs(context, entryPoint, static_cast<GLint>(indexRange.end)))
1263 {
1264 return false;
1265 }
1266
1267 // No op if there are no real indices in the index data (all are primitive restart).
1268 return (indexRange.vertexIndexCount > 0);
1269 }
1270
1271 return true;
1272 }
1273
ValidateBindVertexArrayBase(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)1274 ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context,
1275 angle::EntryPoint entryPoint,
1276 VertexArrayID array)
1277 {
1278 if (!context->isVertexArrayGenerated(array))
1279 {
1280 // The default VAO should always exist
1281 ASSERT(array.value != 0);
1282 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexArray);
1283 return false;
1284 }
1285
1286 return true;
1287 }
1288
ValidateVertexAttribIndex(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index)1289 ANGLE_INLINE bool ValidateVertexAttribIndex(const PrivateState &state,
1290 ErrorSet *errors,
1291 angle::EntryPoint entryPoint,
1292 GLuint index)
1293 {
1294 if (index >= static_cast<GLuint>(state.getCaps().maxVertexAttributes))
1295 {
1296 errors->validationError(entryPoint, GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
1297 return false;
1298 }
1299
1300 return true;
1301 }
1302
1303 bool ValidateLogicOpCommon(const PrivateState &state,
1304 ErrorSet *errors,
1305 angle::EntryPoint entryPoint,
1306 LogicalOperation opcodePacked);
1307 } // namespace gl
1308
1309 #endif // LIBANGLE_VALIDATION_ES_H_
1310