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 ValidateGetTexLevelParameterBase(const Context *context,
866 angle::EntryPoint entryPoint,
867 TextureTarget target,
868 GLint level,
869 GLenum pname,
870 GLsizei *length);
871
872 bool ValidateMapBufferBase(const Context *context,
873 angle::EntryPoint entryPoint,
874 BufferBinding target);
875 bool ValidateIndexedStateQuery(const Context *context,
876 angle::EntryPoint entryPoint,
877 GLenum pname,
878 GLuint index,
879 GLsizei *length);
880 bool ValidateES3TexImage2DParameters(const Context *context,
881 angle::EntryPoint entryPoint,
882 TextureTarget target,
883 GLint level,
884 GLenum internalformat,
885 bool isCompressed,
886 bool isSubImage,
887 GLint xoffset,
888 GLint yoffset,
889 GLint zoffset,
890 GLsizei width,
891 GLsizei height,
892 GLsizei depth,
893 GLint border,
894 GLenum format,
895 GLenum type,
896 GLsizei imageSize,
897 const void *pixels);
898 bool ValidateES3CopyTexImage2DParameters(const Context *context,
899 angle::EntryPoint entryPoint,
900 TextureTarget target,
901 GLint level,
902 GLenum internalformat,
903 bool isSubImage,
904 GLint xoffset,
905 GLint yoffset,
906 GLint zoffset,
907 GLint x,
908 GLint y,
909 GLsizei width,
910 GLsizei height,
911 GLint border);
912 bool ValidateES3TexStorageParametersBase(const Context *context,
913 angle::EntryPoint entryPoint,
914 TextureType target,
915 GLsizei levels,
916 GLenum internalformat,
917 GLsizei width,
918 GLsizei height,
919 GLsizei depth);
920 bool ValidateES3TexStorage2DParameters(const Context *context,
921 angle::EntryPoint entryPoint,
922 TextureType target,
923 GLsizei levels,
924 GLenum internalformat,
925 GLsizei width,
926 GLsizei height,
927 GLsizei depth);
928 bool ValidateES3TexStorage3DParameters(const Context *context,
929 angle::EntryPoint entryPoint,
930 TextureType target,
931 GLsizei levels,
932 GLenum internalformat,
933 GLsizei width,
934 GLsizei height,
935 GLsizei depth);
936
937 bool ValidateGetMultisamplefvBase(const Context *context,
938 angle::EntryPoint entryPoint,
939 GLenum pname,
940 GLuint index,
941 const GLfloat *val);
942 bool ValidateSampleMaskiBase(const PrivateState &state,
943 ErrorSet *errors,
944 angle::EntryPoint entryPoint,
945 GLuint maskNumber,
946 GLbitfield mask);
947
948 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
949 const ProgramExecutable *programExecutable);
950
951 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
952 // implementation format info for incomplete framebuffers. It seems like these queries are
953 // incongruent with the other errors.
954 // Inlined for speed.
955 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,angle::EntryPoint entryPoint,const Framebuffer * framebuffer)956 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
957 angle::EntryPoint entryPoint,
958 const Framebuffer *framebuffer)
959 {
960 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
961 if (!framebufferStatus.isComplete())
962 {
963 ASSERT(framebufferStatus.reason != nullptr);
964 ANGLE_VALIDATION_ERROR(ErrorCode, framebufferStatus.reason);
965 return false;
966 }
967
968 return true;
969 }
970
971 const char *ValidateProgramPipelineDrawStates(const State &state,
972 const Extensions &extensions,
973 ProgramPipeline *programPipeline);
974 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
975 const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode);
976 const char *ValidateProgramPipeline(const Context *context);
977
978 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint);
979
ValidateDrawAttribs(const Context * context,angle::EntryPoint entryPoint,int64_t maxVertex)980 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context,
981 angle::EntryPoint entryPoint,
982 int64_t maxVertex)
983 {
984 // For non-instanced attributes, the maximum vertex must be accessible in the attribute buffers.
985 // For instanced attributes, in non-instanced draw calls only attribute 0 is accessed. In
986 // instanced draw calls, the instance limit is checked in ValidateDrawInstancedAttribs.
987 if (maxVertex >= context->getStateCache().getNonInstancedVertexElementLimit() ||
988 context->getStateCache().getInstancedVertexElementLimit() < 1)
989 {
990 RecordDrawAttribsError(context, entryPoint);
991 return false;
992 }
993
994 return true;
995 }
996
ValidateDrawArraysAttribs(const Context * context,angle::EntryPoint entryPoint,GLint first,GLsizei count)997 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context,
998 angle::EntryPoint entryPoint,
999 GLint first,
1000 GLsizei count)
1001 {
1002 if (!context->isBufferAccessValidationEnabled())
1003 {
1004 return true;
1005 }
1006
1007 // Check the computation of maxVertex doesn't overflow.
1008 // - first < 0 has been checked as an error condition.
1009 // - if count <= 0, skip validating no-op draw calls.
1010 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
1011 ASSERT(first >= 0);
1012 ASSERT(count > 0);
1013 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
1014 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
1015 {
1016 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1017 return false;
1018 }
1019
1020 return ValidateDrawAttribs(context, entryPoint, maxVertex);
1021 }
1022
ValidateDrawInstancedAttribs(const Context * context,angle::EntryPoint entryPoint,GLint primcount,GLuint baseinstance)1023 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context,
1024 angle::EntryPoint entryPoint,
1025 GLint primcount,
1026 GLuint baseinstance)
1027 {
1028 if (!context->isBufferAccessValidationEnabled())
1029 {
1030 return true;
1031 }
1032
1033 // Validate that the buffers bound for the attributes can hold enough vertices for this
1034 // instanced draw. For attributes with a divisor of 0, ValidateDrawAttribs already checks this.
1035 // Thus, the following only checks attributes with a non-zero divisor (i.e. "instanced").
1036 const GLint64 limit = context->getStateCache().getInstancedVertexElementLimit();
1037 if (baseinstance >= limit || primcount > limit - baseinstance)
1038 {
1039 RecordDrawAttribsError(context, entryPoint);
1040 return false;
1041 }
1042
1043 return true;
1044 }
1045
ValidateDrawArraysCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)1046 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
1047 angle::EntryPoint entryPoint,
1048 PrimitiveMode mode,
1049 GLint first,
1050 GLsizei count,
1051 GLsizei primcount)
1052 {
1053 if (first < 0)
1054 {
1055 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeStart);
1056 return false;
1057 }
1058
1059 if (count <= 0)
1060 {
1061 if (count < 0)
1062 {
1063 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1064 return false;
1065 }
1066
1067 // Early exit.
1068 return ValidateDrawBase(context, entryPoint, mode);
1069 }
1070
1071 if (primcount <= 0)
1072 {
1073 if (primcount < 0)
1074 {
1075 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1076 return false;
1077 }
1078 // Early exit.
1079 return ValidateDrawBase(context, entryPoint, mode);
1080 }
1081
1082 if (!ValidateDrawBase(context, entryPoint, mode))
1083 {
1084 return false;
1085 }
1086
1087 if (context->getStateCache().isTransformFeedbackActiveUnpaused() &&
1088 !context->supportsGeometryOrTesselation())
1089 {
1090 const State &state = context->getState();
1091 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
1092 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
1093 {
1094 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
1095 return false;
1096 }
1097 }
1098
1099 return ValidateDrawArraysAttribs(context, entryPoint, first, count);
1100 }
1101
ValidateDrawElementsBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,DrawElementsType type)1102 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
1103 angle::EntryPoint entryPoint,
1104 PrimitiveMode mode,
1105 DrawElementsType type)
1106 {
1107 if (!context->getStateCache().isValidDrawElementsType(type))
1108 {
1109 if (type == DrawElementsType::UnsignedInt)
1110 {
1111 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
1112 return false;
1113 }
1114
1115 ASSERT(type == DrawElementsType::InvalidEnum);
1116 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, err::kEnumInvalid);
1117 return false;
1118 }
1119
1120 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
1121 if (drawElementsError)
1122 {
1123 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
1124 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
1125 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, errorMessage);
1126 return false;
1127 }
1128
1129 // Note that we are missing overflow checks for active transform feedback buffers.
1130 return true;
1131 }
1132
ValidateDrawElementsCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)1133 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
1134 angle::EntryPoint entryPoint,
1135 PrimitiveMode mode,
1136 GLsizei count,
1137 DrawElementsType type,
1138 const void *indices,
1139 GLsizei primcount)
1140 {
1141 if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
1142 {
1143 return false;
1144 }
1145
1146 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
1147
1148 if (context->isWebGL())
1149 {
1150 GLuint typeBytes = GetDrawElementsTypeSize(type);
1151
1152 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
1153 {
1154 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
1155 // The offset arguments to drawElements and [...], must be a multiple of the size of the
1156 // data type passed to the call, or an INVALID_OPERATION error is generated.
1157 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
1158 return false;
1159 }
1160
1161 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
1162 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
1163 // error is generated.
1164 if (reinterpret_cast<intptr_t>(indices) < 0)
1165 {
1166 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeOffset);
1167 return false;
1168 }
1169 }
1170
1171 if (count <= 0)
1172 {
1173 if (count < 0)
1174 {
1175 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1176 return false;
1177 }
1178
1179 // Early exit.
1180 return ValidateDrawBase(context, entryPoint, mode);
1181 }
1182
1183 if (!ValidateDrawBase(context, entryPoint, mode))
1184 {
1185 return false;
1186 }
1187
1188 const State &state = context->getState();
1189 const VertexArray *vao = state.getVertexArray();
1190 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1191
1192 if (!elementArrayBuffer)
1193 {
1194 if (!indices)
1195 {
1196 // This is an application error that would normally result in a crash, but we catch
1197 // it and return an error
1198 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
1199 return false;
1200 }
1201 }
1202 else
1203 {
1204 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
1205 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
1206 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
1207 constexpr uint64_t kMaxTypeSize = 8;
1208 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
1209 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
1210 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
1211
1212 uint64_t elementCount = static_cast<uint64_t>(count);
1213 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
1214
1215 // Doing the multiplication here is overflow-safe
1216 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
1217
1218 // The offset can be any value, check for overflows
1219 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
1220 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
1221 if (elementDataSizeWithOffset < elementDataSizeNoOffset)
1222 {
1223 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1224 return false;
1225 }
1226
1227 // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064
1228 if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) &&
1229 (primcount > 0))
1230 {
1231 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
1232 return false;
1233 }
1234 }
1235
1236 if (context->isBufferAccessValidationEnabled() && primcount > 0)
1237 {
1238 // Use the parameter buffer to retrieve and cache the index range.
1239 // TODO: this calculation should take basevertex into account for
1240 // glDrawElementsInstancedBaseVertexBaseInstanceEXT. http://anglebug.com/8448
1241 IndexRange indexRange{IndexRange::Undefined()};
1242 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
1243
1244 // If we use an index greater than our maximum supported index range, return an error.
1245 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1246 // always return an error if possible here.
1247 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1248 {
1249 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1250 return false;
1251 }
1252
1253 if (!ValidateDrawAttribs(context, entryPoint, static_cast<GLint>(indexRange.end)))
1254 {
1255 return false;
1256 }
1257
1258 // No op if there are no real indices in the index data (all are primitive restart).
1259 return (indexRange.vertexIndexCount > 0);
1260 }
1261
1262 return true;
1263 }
1264
ValidateBindVertexArrayBase(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)1265 ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context,
1266 angle::EntryPoint entryPoint,
1267 VertexArrayID array)
1268 {
1269 if (!context->isVertexArrayGenerated(array))
1270 {
1271 // The default VAO should always exist
1272 ASSERT(array.value != 0);
1273 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexArray);
1274 return false;
1275 }
1276
1277 return true;
1278 }
1279
ValidateVertexAttribIndex(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index)1280 ANGLE_INLINE bool ValidateVertexAttribIndex(const PrivateState &state,
1281 ErrorSet *errors,
1282 angle::EntryPoint entryPoint,
1283 GLuint index)
1284 {
1285 if (index >= static_cast<GLuint>(state.getCaps().maxVertexAttributes))
1286 {
1287 errors->validationError(entryPoint, GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
1288 return false;
1289 }
1290
1291 return true;
1292 }
1293
1294 bool ValidateLogicOpCommon(const PrivateState &state,
1295 ErrorSet *errors,
1296 angle::EntryPoint entryPoint,
1297 LogicalOperation opcodePacked);
1298 } // namespace gl
1299
1300 #endif // LIBANGLE_VALIDATION_ES_H_
1301