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
ValidateUniformCommonBase(const Context * context,angle::EntryPoint entryPoint,const Program * program,UniformLocation location,GLsizei count,const LinkedUniform ** uniformOut)321 ANGLE_INLINE bool ValidateUniformCommonBase(const Context *context,
322 angle::EntryPoint entryPoint,
323 const Program *program,
324 UniformLocation location,
325 GLsizei count,
326 const LinkedUniform **uniformOut)
327 {
328 // TODO(Jiajia): Add image uniform check in future.
329 if (count < 0)
330 {
331 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
332 return false;
333 }
334
335 if (!program)
336 {
337 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidProgramName);
338 return false;
339 }
340
341 if (!program->isLinked())
342 {
343 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kProgramNotLinked);
344 return false;
345 }
346
347 if (location.value == -1)
348 {
349 // Silently ignore the uniform command
350 return false;
351 }
352
353 const ProgramExecutable &executable = program->getExecutable();
354 const auto &uniformLocations = executable.getUniformLocations();
355 size_t castedLocation = static_cast<size_t>(location.value);
356 if (castedLocation >= uniformLocations.size())
357 {
358 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformLocation);
359 return false;
360 }
361
362 const auto &uniformLocation = uniformLocations[castedLocation];
363 if (uniformLocation.ignored)
364 {
365 // Silently ignore the uniform command
366 return false;
367 }
368
369 if (!uniformLocation.used())
370 {
371 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformLocation);
372 return false;
373 }
374
375 const LinkedUniform &uniform = executable.getUniformByIndex(uniformLocation.index);
376
377 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
378 if (count > 1 && !uniform.isArray())
379 {
380 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidUniformCount);
381 return false;
382 }
383
384 *uniformOut = &uniform;
385 return true;
386 }
387
388 bool ValidateUniform1ivValue(const Context *context,
389 angle::EntryPoint entryPoint,
390 GLenum uniformType,
391 GLsizei count,
392 const GLint *value);
393
ValidateUniformValue(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,GLenum uniformType)394 ANGLE_INLINE bool ValidateUniformValue(const Context *context,
395 angle::EntryPoint entryPoint,
396 GLenum valueType,
397 GLenum uniformType)
398 {
399 // Check that the value type is compatible with uniform type.
400 // Do the cheaper test first, for a little extra speed.
401 if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
402 {
403 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kUniformSizeMismatch);
404 return false;
405 }
406 return true;
407 }
408
409 bool ValidateUniformMatrixValue(const Context *context,
410 angle::EntryPoint entryPoint,
411 GLenum valueType,
412 GLenum uniformType);
413 bool ValidateUniform(const Context *context,
414 angle::EntryPoint entryPoint,
415 GLenum uniformType,
416 UniformLocation location,
417 GLsizei count);
418 bool ValidateUniformMatrix(const Context *context,
419 angle::EntryPoint entryPoint,
420 GLenum matrixType,
421 UniformLocation location,
422 GLsizei count,
423 GLboolean transpose);
424 bool ValidateGetBooleanvRobustANGLE(const Context *context,
425 angle::EntryPoint entryPoint,
426 GLenum pname,
427 GLsizei bufSize,
428 const GLsizei *length,
429 const GLboolean *params);
430 bool ValidateGetFloatvRobustANGLE(const Context *context,
431 angle::EntryPoint entryPoint,
432 GLenum pname,
433 GLsizei bufSize,
434 const GLsizei *length,
435 const GLfloat *params);
436 bool ValidateStateQuery(const Context *context,
437 angle::EntryPoint entryPoint,
438 GLenum pname,
439 GLenum *nativeType,
440 unsigned int *numParams);
441 bool ValidateGetIntegervRobustANGLE(const Context *context,
442 angle::EntryPoint entryPoint,
443 GLenum pname,
444 GLsizei bufSize,
445 const GLsizei *length,
446 const GLint *data);
447 bool ValidateGetInteger64vRobustANGLE(const Context *context,
448 angle::EntryPoint entryPoint,
449 GLenum pname,
450 GLsizei bufSize,
451 const GLsizei *length,
452 GLint64 *data);
453 bool ValidateRobustStateQuery(const Context *context,
454 angle::EntryPoint entryPoint,
455 GLenum pname,
456 GLsizei bufSize,
457 GLenum *nativeType,
458 unsigned int *numParams);
459
460 bool ValidateCopyImageSubDataBase(const Context *context,
461 angle::EntryPoint entryPoint,
462 GLuint srcName,
463 GLenum srcTarget,
464 GLint srcLevel,
465 GLint srcX,
466 GLint srcY,
467 GLint srcZ,
468 GLuint dstName,
469 GLenum dstTarget,
470 GLint dstLevel,
471 GLint dstX,
472 GLint dstY,
473 GLint dstZ,
474 GLsizei srcWidth,
475 GLsizei srcHeight,
476 GLsizei srcDepth);
477
478 bool ValidateCopyTexImageParametersBase(const Context *context,
479 angle::EntryPoint entryPoint,
480 TextureTarget target,
481 GLint level,
482 GLenum internalformat,
483 bool isSubImage,
484 GLint xoffset,
485 GLint yoffset,
486 GLint zoffset,
487 GLint x,
488 GLint y,
489 GLsizei width,
490 GLsizei height,
491 GLint border,
492 Format *textureFormatOut);
493
494 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode);
495 const char *ValidateDrawElementsStates(const Context *context);
496
ValidateDrawBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode)497 ANGLE_INLINE bool ValidateDrawBase(const Context *context,
498 angle::EntryPoint entryPoint,
499 PrimitiveMode mode)
500 {
501 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesErrorString(
502 context, &context->getPrivateStateCache());
503 if (drawStatesError)
504 {
505 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
506 GLenum errorCode = context->getStateCache().getBasicDrawElementsErrorCode();
507 ANGLE_VALIDATION_ERROR(errorCode, errorMessage);
508 return false;
509 }
510
511 if (!context->getStateCache().isValidDrawMode(mode))
512 {
513 RecordDrawModeError(context, entryPoint, mode);
514 return false;
515 }
516
517 return true;
518 }
519
520 bool ValidateDrawArraysInstancedBase(const Context *context,
521 angle::EntryPoint entryPoint,
522 PrimitiveMode mode,
523 GLint first,
524 GLsizei count,
525 GLsizei primcount,
526 GLuint baseinstance);
527 bool ValidateDrawArraysInstancedANGLE(const Context *context,
528 angle::EntryPoint entryPoint,
529 PrimitiveMode mode,
530 GLint first,
531 GLsizei count,
532 GLsizei primcount);
533 bool ValidateDrawArraysInstancedEXT(const Context *context,
534 angle::EntryPoint entryPoint,
535 PrimitiveMode mode,
536 GLint first,
537 GLsizei count,
538 GLsizei primcount);
539
540 bool ValidateDrawElementsInstancedBase(const Context *context,
541 angle::EntryPoint entryPoint,
542 PrimitiveMode mode,
543 GLsizei count,
544 DrawElementsType type,
545 const void *indices,
546 GLsizei primcount,
547 GLuint baseinstance);
548 bool ValidateDrawElementsInstancedANGLE(const Context *context,
549 angle::EntryPoint entryPoint,
550 PrimitiveMode mode,
551 GLsizei count,
552 DrawElementsType type,
553 const void *indices,
554 GLsizei primcount);
555 bool ValidateDrawElementsInstancedEXT(const Context *context,
556 angle::EntryPoint entryPoint,
557 PrimitiveMode mode,
558 GLsizei count,
559 DrawElementsType type,
560 const void *indices,
561 GLsizei primcount);
562
563 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint);
564
565 bool ValidateGetUniformBase(const Context *context,
566 angle::EntryPoint entryPoint,
567 ShaderProgramID program,
568 UniformLocation location);
569 bool ValidateSizedGetUniform(const Context *context,
570 angle::EntryPoint entryPoint,
571 ShaderProgramID program,
572 UniformLocation location,
573 GLsizei bufSize,
574 GLsizei *length);
575 bool ValidateGetnUniformfvEXT(const Context *context,
576 angle::EntryPoint entryPoint,
577 ShaderProgramID program,
578 UniformLocation location,
579 GLsizei bufSize,
580 const GLfloat *params);
581 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
582 angle::EntryPoint entryPoint,
583 ShaderProgramID program,
584 UniformLocation location,
585 GLsizei bufSize,
586 const GLsizei *length,
587 const GLfloat *params);
588 bool ValidateGetnUniformivEXT(const Context *context,
589 angle::EntryPoint entryPoint,
590 ShaderProgramID program,
591 UniformLocation location,
592 GLsizei bufSize,
593 const GLint *params);
594 bool ValidateGetnUniformivRobustANGLE(const Context *context,
595 angle::EntryPoint entryPoint,
596 ShaderProgramID program,
597 UniformLocation location,
598 GLsizei bufSize,
599 const GLsizei *length,
600 const GLint *params);
601 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
602 angle::EntryPoint entryPoint,
603 ShaderProgramID program,
604 UniformLocation location,
605 GLsizei bufSize,
606 const GLsizei *length,
607 const GLuint *params);
608 bool ValidateGetUniformfvRobustANGLE(const Context *context,
609 angle::EntryPoint entryPoint,
610 ShaderProgramID program,
611 UniformLocation location,
612 GLsizei bufSize,
613 const GLsizei *length,
614 const GLfloat *params);
615 bool ValidateGetUniformivRobustANGLE(const Context *context,
616 angle::EntryPoint entryPoint,
617 ShaderProgramID program,
618 UniformLocation location,
619 GLsizei bufSize,
620 const GLsizei *length,
621 const GLint *params);
622 bool ValidateGetUniformuivRobustANGLE(const Context *context,
623 angle::EntryPoint entryPoint,
624 ShaderProgramID program,
625 UniformLocation location,
626 GLsizei bufSize,
627 const GLsizei *length,
628 const GLuint *params);
629
630 bool ValidateDiscardFramebufferBase(const Context *context,
631 angle::EntryPoint entryPoint,
632 GLenum target,
633 GLsizei numAttachments,
634 const GLenum *attachments,
635 bool defaultFramebuffer);
636
637 bool ValidateInsertEventMarkerEXT(const Context *context,
638 angle::EntryPoint entryPoint,
639 GLsizei length,
640 const char *marker);
641 bool ValidatePushGroupMarkerEXT(const Context *context,
642 angle::EntryPoint entryPoint,
643 GLsizei length,
644 const char *marker);
645 bool ValidateEGLImageObject(const Context *context,
646 angle::EntryPoint entryPoint,
647 TextureType type,
648 egl::ImageID image);
649 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
650 angle::EntryPoint entryPoint,
651 TextureType type,
652 egl::ImageID image);
653 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
654 angle::EntryPoint entryPoint,
655 GLenum target,
656 egl::ImageID image);
657
658 bool ValidateProgramBinaryBase(const Context *context,
659 angle::EntryPoint entryPoint,
660 ShaderProgramID program,
661 GLenum binaryFormat,
662 const void *binary,
663 GLint length);
664 bool ValidateGetProgramBinaryBase(const Context *context,
665 angle::EntryPoint entryPoint,
666 ShaderProgramID program,
667 GLsizei bufSize,
668 const GLsizei *length,
669 const GLenum *binaryFormat,
670 const void *binary);
671
672 bool ValidateDrawBuffersBase(const Context *context,
673 angle::EntryPoint entryPoint,
674 GLsizei n,
675 const GLenum *bufs);
676
677 bool ValidateGetBufferPointervBase(const Context *context,
678 angle::EntryPoint entryPoint,
679 BufferBinding target,
680 GLenum pname,
681 GLsizei *length,
682 void *const *params);
683 bool ValidateUnmapBufferBase(const Context *context,
684 angle::EntryPoint entryPoint,
685 BufferBinding target);
686 bool ValidateMapBufferRangeBase(const Context *context,
687 angle::EntryPoint entryPoint,
688 BufferBinding target,
689 GLintptr offset,
690 GLsizeiptr length,
691 GLbitfield access);
692 bool ValidateFlushMappedBufferRangeBase(const Context *context,
693 angle::EntryPoint entryPoint,
694 BufferBinding target,
695 GLintptr offset,
696 GLsizeiptr length);
697
698 bool ValidateGenOrDelete(const Context *context,
699 angle::EntryPoint entryPoint,
700 GLint n,
701 const void *ids);
702
703 bool ValidateRobustEntryPoint(const Context *context,
704 angle::EntryPoint entryPoint,
705 GLsizei bufSize);
706 bool ValidateRobustBufferSize(const Context *context,
707 angle::EntryPoint entryPoint,
708 GLsizei bufSize,
709 GLsizei numParams);
710
711 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
712 angle::EntryPoint entryPoint,
713 GLenum target,
714 GLenum attachment,
715 GLenum pname,
716 GLsizei *numParams);
717
718 bool ValidateGetFramebufferParameterivBase(const Context *context,
719 angle::EntryPoint entryPoint,
720 GLenum target,
721 GLenum pname,
722 const GLint *params);
723
724 bool ValidateGetBufferParameterBase(const Context *context,
725 angle::EntryPoint entryPoint,
726 BufferBinding target,
727 GLenum pname,
728 bool pointerVersion,
729 GLsizei *numParams);
730
731 bool ValidateGetProgramivBase(const Context *context,
732 angle::EntryPoint entryPoint,
733 ShaderProgramID program,
734 GLenum pname,
735 GLsizei *numParams);
736
737 bool ValidateGetRenderbufferParameterivBase(const Context *context,
738 angle::EntryPoint entryPoint,
739 GLenum target,
740 GLenum pname,
741 GLsizei *length);
742
743 bool ValidateGetShaderivBase(const Context *context,
744 angle::EntryPoint entryPoint,
745 ShaderProgramID shader,
746 GLenum pname,
747 GLsizei *length);
748
749 bool ValidateGetTexParameterBase(const Context *context,
750 angle::EntryPoint entryPoint,
751 TextureType target,
752 GLenum pname,
753 GLsizei *length);
754
755 template <typename ParamType>
756 bool ValidateTexParameterBase(const Context *context,
757 angle::EntryPoint entryPoint,
758 TextureType target,
759 GLenum pname,
760 GLsizei bufSize,
761 bool vectorParams,
762 const ParamType *params);
763
764 bool ValidateGetVertexAttribBase(const Context *context,
765 angle::EntryPoint entryPoint,
766 GLuint index,
767 GLenum pname,
768 GLsizei *length,
769 bool pointer,
770 bool pureIntegerEntryPoint);
771
ValidateVertexFormat(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribTypeCase validation)772 ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
773 angle::EntryPoint entryPoint,
774 GLuint index,
775 GLint size,
776 VertexAttribTypeCase validation)
777 {
778 const Caps &caps = context->getCaps();
779 if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
780 {
781 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
782 return false;
783 }
784
785 switch (validation)
786 {
787 case VertexAttribTypeCase::Invalid:
788 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kInvalidType);
789 return false;
790 case VertexAttribTypeCase::Valid:
791 if (size < 1 || size > 4)
792 {
793 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
794 return false;
795 }
796 break;
797 case VertexAttribTypeCase::ValidSize4Only:
798 if (size != 4)
799 {
800 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize2101010);
801 return false;
802 }
803 break;
804 case VertexAttribTypeCase::ValidSize3or4:
805 if (size != 3 && size != 4)
806 {
807 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexAttribSize1010102);
808 return false;
809 }
810 break;
811 }
812
813 return true;
814 }
815
816 // 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)817 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
818 angle::EntryPoint entryPoint,
819 GLuint index,
820 GLint size,
821 VertexAttribType type)
822 {
823 return ValidateVertexFormat(context, entryPoint, index, size,
824 context->getStateCache().getVertexAttribTypeValidation(type));
825 }
826
ValidateIntegerVertexFormat(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type)827 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
828 angle::EntryPoint entryPoint,
829 GLuint index,
830 GLint size,
831 VertexAttribType type)
832 {
833 return ValidateVertexFormat(
834 context, entryPoint, index, size,
835 context->getStateCache().getIntegerVertexAttribTypeValidation(type));
836 }
837
ValidateColorMasksForSharedExponentColorBuffers(const BlendStateExt & blendState,const Framebuffer * framebuffer)838 ANGLE_INLINE bool ValidateColorMasksForSharedExponentColorBuffers(const BlendStateExt &blendState,
839 const Framebuffer *framebuffer)
840 {
841 // Get a mask of draw buffers that have color writemasks
842 // incompatible with shared exponent color buffers.
843 // The compatible writemasks are RGBA, RGB0, 000A, 0000.
844 const BlendStateExt::ColorMaskStorage::Type rgbEnabledBits =
845 blendState.expandColorMaskValue(true, true, true, false);
846 const BlendStateExt::ColorMaskStorage::Type colorMaskNoAlphaBits =
847 blendState.getColorMaskBits() & rgbEnabledBits;
848 const DrawBufferMask incompatibleDiffMask =
849 BlendStateExt::ColorMaskStorage::GetDiffMask(colorMaskNoAlphaBits, 0) &
850 BlendStateExt::ColorMaskStorage::GetDiffMask(colorMaskNoAlphaBits, rgbEnabledBits);
851
852 const DrawBufferMask sharedExponentBufferMask =
853 framebuffer->getActiveSharedExponentColorAttachmentDrawBufferMask();
854 return (sharedExponentBufferMask & incompatibleDiffMask).none();
855 }
856
857 bool ValidateRobustCompressedTexImageBase(const Context *context,
858 angle::EntryPoint entryPoint,
859 GLsizei imageSize,
860 GLsizei dataSize);
861
862 bool ValidateVertexAttribIndex(const PrivateState &state,
863 ErrorSet *errors,
864 angle::EntryPoint entryPoint,
865 GLuint index);
866
867 bool ValidateGetActiveUniformBlockivBase(const Context *context,
868 angle::EntryPoint entryPoint,
869 ShaderProgramID program,
870 UniformBlockIndex uniformBlockIndex,
871 GLenum pname,
872 GLsizei *length);
873
874 template <typename ParamType>
875 bool ValidateGetSamplerParameterBase(const Context *context,
876 angle::EntryPoint entryPoint,
877 SamplerID sampler,
878 GLenum pname,
879 GLsizei *length,
880 const ParamType *params);
881
882 template <typename ParamType>
883 bool ValidateSamplerParameterBase(const Context *context,
884 angle::EntryPoint entryPoint,
885 SamplerID sampler,
886 GLenum pname,
887 GLsizei bufSize,
888 bool vectorParams,
889 const ParamType *params);
890
891 bool ValidateGetInternalFormativBase(const Context *context,
892 angle::EntryPoint entryPoint,
893 GLenum target,
894 GLenum internalformat,
895 GLenum pname,
896 GLsizei bufSize,
897 GLsizei *numParams);
898
899 bool ValidateFramebufferNotMultisampled(const Context *context,
900 angle::EntryPoint entryPoint,
901 const Framebuffer *framebuffer,
902 bool checkReadBufferResourceSamples);
903
904 bool ValidateMultitextureUnit(const PrivateState &state,
905 ErrorSet *errors,
906 angle::EntryPoint entryPoint,
907 GLenum texture);
908
909 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
910 angle::EntryPoint entryPoint,
911 PrimitiveMode transformFeedbackPrimitiveMode,
912 PrimitiveMode renderPrimitiveMode);
913
914 // Common validation for 2D and 3D variants of TexStorage*Multisample.
915 bool ValidateTexStorageMultisample(const Context *context,
916 angle::EntryPoint entryPoint,
917 TextureType target,
918 GLsizei samples,
919 GLint internalFormat,
920 GLsizei width,
921 GLsizei height);
922
923 bool ValidateTexStorage2DMultisampleBase(const Context *context,
924 angle::EntryPoint entryPoint,
925 TextureType target,
926 GLsizei samples,
927 GLint internalFormat,
928 GLsizei width,
929 GLsizei height);
930
931 bool ValidateTexStorage3DMultisampleBase(const Context *context,
932 angle::EntryPoint entryPoint,
933 TextureType target,
934 GLsizei samples,
935 GLenum internalformat,
936 GLsizei width,
937 GLsizei height,
938 GLsizei depth);
939
940 bool ValidateGetTexLevelParameterBase(const Context *context,
941 angle::EntryPoint entryPoint,
942 TextureTarget target,
943 GLint level,
944 GLenum pname,
945 GLsizei *length);
946
947 bool ValidateMapBufferBase(const Context *context,
948 angle::EntryPoint entryPoint,
949 BufferBinding target);
950 bool ValidateIndexedStateQuery(const Context *context,
951 angle::EntryPoint entryPoint,
952 GLenum pname,
953 GLuint index,
954 GLsizei *length);
955 bool ValidateES3TexImage2DParameters(const Context *context,
956 angle::EntryPoint entryPoint,
957 TextureTarget target,
958 GLint level,
959 GLenum internalformat,
960 bool isCompressed,
961 bool isSubImage,
962 GLint xoffset,
963 GLint yoffset,
964 GLint zoffset,
965 GLsizei width,
966 GLsizei height,
967 GLsizei depth,
968 GLint border,
969 GLenum format,
970 GLenum type,
971 GLsizei imageSize,
972 const void *pixels);
973 bool ValidateES3CopyTexImage2DParameters(const Context *context,
974 angle::EntryPoint entryPoint,
975 TextureTarget target,
976 GLint level,
977 GLenum internalformat,
978 bool isSubImage,
979 GLint xoffset,
980 GLint yoffset,
981 GLint zoffset,
982 GLint x,
983 GLint y,
984 GLsizei width,
985 GLsizei height,
986 GLint border);
987 bool ValidateES3TexStorageParametersBase(const Context *context,
988 angle::EntryPoint entryPoint,
989 TextureType target,
990 GLsizei levels,
991 GLenum internalformat,
992 GLsizei width,
993 GLsizei height,
994 GLsizei depth);
995 bool ValidateES3TexStorage2DParameters(const Context *context,
996 angle::EntryPoint entryPoint,
997 TextureType target,
998 GLsizei levels,
999 GLenum internalformat,
1000 GLsizei width,
1001 GLsizei height,
1002 GLsizei depth);
1003 bool ValidateES3TexStorage3DParameters(const Context *context,
1004 angle::EntryPoint entryPoint,
1005 TextureType target,
1006 GLsizei levels,
1007 GLenum internalformat,
1008 GLsizei width,
1009 GLsizei height,
1010 GLsizei depth);
1011
1012 bool ValidateGetMultisamplefvBase(const Context *context,
1013 angle::EntryPoint entryPoint,
1014 GLenum pname,
1015 GLuint index,
1016 const GLfloat *val);
1017 bool ValidateSampleMaskiBase(const PrivateState &state,
1018 ErrorSet *errors,
1019 angle::EntryPoint entryPoint,
1020 GLuint maskNumber,
1021 GLbitfield mask);
1022
1023 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
1024 const ProgramExecutable *programExecutable);
1025
1026 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
1027 // implementation format info for incomplete framebuffers. It seems like these queries are
1028 // incongruent with the other errors.
1029 // Inlined for speed.
1030 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,angle::EntryPoint entryPoint,const Framebuffer * framebuffer)1031 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
1032 angle::EntryPoint entryPoint,
1033 const Framebuffer *framebuffer)
1034 {
1035 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
1036 if (!framebufferStatus.isComplete())
1037 {
1038 ASSERT(framebufferStatus.reason != nullptr);
1039 ANGLE_VALIDATION_ERROR(ErrorCode, framebufferStatus.reason);
1040 return false;
1041 }
1042
1043 return true;
1044 }
1045
1046 const char *ValidateProgramPipelineDrawStates(const State &state,
1047 const Extensions &extensions,
1048 ProgramPipeline *programPipeline);
1049 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
1050 const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode);
1051 const char *ValidateProgramPipeline(const Context *context);
1052
1053 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint);
1054
ValidateDrawAttribs(const Context * context,angle::EntryPoint entryPoint,int64_t maxVertex)1055 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context,
1056 angle::EntryPoint entryPoint,
1057 int64_t maxVertex)
1058 {
1059 // For non-instanced attributes, the maximum vertex must be accessible in the attribute buffers.
1060 // For instanced attributes, in non-instanced draw calls only attribute 0 is accessed. In
1061 // instanced draw calls, the instance limit is checked in ValidateDrawInstancedAttribs.
1062 if (maxVertex >= context->getStateCache().getNonInstancedVertexElementLimit() ||
1063 context->getStateCache().getInstancedVertexElementLimit() < 1)
1064 {
1065 RecordDrawAttribsError(context, entryPoint);
1066 return false;
1067 }
1068
1069 return true;
1070 }
1071
ValidateDrawArraysAttribs(const Context * context,angle::EntryPoint entryPoint,GLint first,GLsizei count)1072 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context,
1073 angle::EntryPoint entryPoint,
1074 GLint first,
1075 GLsizei count)
1076 {
1077 if (!context->isBufferAccessValidationEnabled())
1078 {
1079 return true;
1080 }
1081
1082 // Check the computation of maxVertex doesn't overflow.
1083 // - first < 0 has been checked as an error condition.
1084 // - if count <= 0, skip validating no-op draw calls.
1085 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
1086 ASSERT(first >= 0);
1087 ASSERT(count > 0);
1088 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
1089 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
1090 {
1091 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1092 return false;
1093 }
1094
1095 return ValidateDrawAttribs(context, entryPoint, maxVertex);
1096 }
1097
ValidateDrawInstancedAttribs(const Context * context,angle::EntryPoint entryPoint,GLint primcount,GLuint baseinstance)1098 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context,
1099 angle::EntryPoint entryPoint,
1100 GLint primcount,
1101 GLuint baseinstance)
1102 {
1103 if (!context->isBufferAccessValidationEnabled())
1104 {
1105 return true;
1106 }
1107
1108 // Validate that the buffers bound for the attributes can hold enough vertices for this
1109 // instanced draw. For attributes with a divisor of 0, ValidateDrawAttribs already checks this.
1110 // Thus, the following only checks attributes with a non-zero divisor (i.e. "instanced").
1111 const GLint64 limit = context->getStateCache().getInstancedVertexElementLimit();
1112 if (baseinstance >= limit || primcount > limit - baseinstance)
1113 {
1114 RecordDrawAttribsError(context, entryPoint);
1115 return false;
1116 }
1117
1118 return true;
1119 }
1120
ValidateDrawArraysCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)1121 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
1122 angle::EntryPoint entryPoint,
1123 PrimitiveMode mode,
1124 GLint first,
1125 GLsizei count,
1126 GLsizei primcount)
1127 {
1128 if (first < 0)
1129 {
1130 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeStart);
1131 return false;
1132 }
1133
1134 if (count <= 0)
1135 {
1136 if (count < 0)
1137 {
1138 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1139 return false;
1140 }
1141
1142 // Early exit.
1143 return ValidateDrawBase(context, entryPoint, mode);
1144 }
1145
1146 if (primcount <= 0)
1147 {
1148 if (primcount < 0)
1149 {
1150 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1151 return false;
1152 }
1153 // Early exit.
1154 return ValidateDrawBase(context, entryPoint, mode);
1155 }
1156
1157 if (!ValidateDrawBase(context, entryPoint, mode))
1158 {
1159 return false;
1160 }
1161
1162 if (context->getStateCache().isTransformFeedbackActiveUnpaused() &&
1163 !context->supportsGeometryOrTesselation())
1164 {
1165 const State &state = context->getState();
1166 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
1167 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
1168 {
1169 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
1170 return false;
1171 }
1172 }
1173
1174 return ValidateDrawArraysAttribs(context, entryPoint, first, count);
1175 }
1176
ValidateDrawElementsBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,DrawElementsType type)1177 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
1178 angle::EntryPoint entryPoint,
1179 PrimitiveMode mode,
1180 DrawElementsType type)
1181 {
1182 if (!context->getStateCache().isValidDrawElementsType(type))
1183 {
1184 if (type == DrawElementsType::UnsignedInt)
1185 {
1186 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
1187 return false;
1188 }
1189
1190 ASSERT(type == DrawElementsType::InvalidEnum);
1191 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, err::kEnumInvalid);
1192 return false;
1193 }
1194
1195 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
1196 if (drawElementsError)
1197 {
1198 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
1199 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
1200 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, errorMessage);
1201 return false;
1202 }
1203
1204 // Note that we are missing overflow checks for active transform feedback buffers.
1205 return true;
1206 }
1207
ValidateDrawElementsCommon(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)1208 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
1209 angle::EntryPoint entryPoint,
1210 PrimitiveMode mode,
1211 GLsizei count,
1212 DrawElementsType type,
1213 const void *indices,
1214 GLsizei primcount)
1215 {
1216 if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
1217 {
1218 return false;
1219 }
1220
1221 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
1222
1223 const State &state = context->getState();
1224 const VertexArray *vao = state.getVertexArray();
1225 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1226 GLuint typeBytes = GetDrawElementsTypeSize(type);
1227
1228 if (elementArrayBuffer != nullptr)
1229 {
1230 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
1231 {
1232 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements:
1233 // The offset arguments to drawElements and [...], must be a multiple of the size of the
1234 // data type passed to the call, or an INVALID_OPERATION error is generated.
1235 // [GLES 3.2] Section 6.3:
1236 // Clients must align data elements consistently with the requirements of the
1237 // client platform, with an additional base-level requirement that an offset within a
1238 // buffer to a datum comprising N basic machine units be a multiple of N.
1239 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
1240 return false;
1241 }
1242
1243 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
1244 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
1245 // error is generated.
1246 if (reinterpret_cast<intptr_t>(indices) < 0)
1247 {
1248 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeOffset);
1249 return false;
1250 }
1251 }
1252
1253 if (count <= 0)
1254 {
1255 if (count < 0)
1256 {
1257 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, err::kNegativeCount);
1258 return false;
1259 }
1260
1261 // Early exit.
1262 return ValidateDrawBase(context, entryPoint, mode);
1263 }
1264
1265 if (!ValidateDrawBase(context, entryPoint, mode))
1266 {
1267 return false;
1268 }
1269
1270 if (!elementArrayBuffer)
1271 {
1272 if (!indices)
1273 {
1274 // This is an application error that would normally result in a crash, but we catch
1275 // it and return an error
1276 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
1277 return false;
1278 }
1279 }
1280 else
1281 {
1282 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
1283 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
1284 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
1285 constexpr uint64_t kMaxTypeSize = 8;
1286 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
1287 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
1288 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
1289
1290 uint64_t elementCount = static_cast<uint64_t>(count);
1291 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
1292
1293 // Doing the multiplication here is overflow-safe
1294 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
1295
1296 // The offset can be any value, check for overflows
1297 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
1298 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
1299 if (elementDataSizeWithOffset < elementDataSizeNoOffset)
1300 {
1301 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kIntegerOverflow);
1302 return false;
1303 }
1304
1305 // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064
1306 if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) &&
1307 (primcount > 0))
1308 {
1309 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
1310 return false;
1311 }
1312 }
1313
1314 if (context->isBufferAccessValidationEnabled() && primcount > 0)
1315 {
1316 // Use the parameter buffer to retrieve and cache the index range.
1317 // TODO: this calculation should take basevertex into account for
1318 // glDrawElementsInstancedBaseVertexBaseInstanceEXT. http://anglebug.com/41481166
1319 IndexRange indexRange{IndexRange::Undefined()};
1320 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
1321
1322 // If we use an index greater than our maximum supported index range, return an error.
1323 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1324 // always return an error if possible here.
1325 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1326 {
1327 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1328 return false;
1329 }
1330
1331 if (!ValidateDrawAttribs(context, entryPoint, static_cast<GLint>(indexRange.end)))
1332 {
1333 return false;
1334 }
1335
1336 // No op if there are no real indices in the index data (all are primitive restart).
1337 return (indexRange.vertexIndexCount > 0);
1338 }
1339
1340 return true;
1341 }
1342
ValidateBindVertexArrayBase(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)1343 ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context,
1344 angle::EntryPoint entryPoint,
1345 VertexArrayID array)
1346 {
1347 if (!context->isVertexArrayGenerated(array))
1348 {
1349 // The default VAO should always exist
1350 ASSERT(array.value != 0);
1351 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, err::kInvalidVertexArray);
1352 return false;
1353 }
1354
1355 return true;
1356 }
1357
ValidateVertexAttribIndex(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index)1358 ANGLE_INLINE bool ValidateVertexAttribIndex(const PrivateState &state,
1359 ErrorSet *errors,
1360 angle::EntryPoint entryPoint,
1361 GLuint index)
1362 {
1363 if (index >= static_cast<GLuint>(state.getCaps().maxVertexAttributes))
1364 {
1365 errors->validationError(entryPoint, GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
1366 return false;
1367 }
1368
1369 return true;
1370 }
1371
1372 bool ValidateLogicOpCommon(const PrivateState &state,
1373 ErrorSet *errors,
1374 angle::EntryPoint entryPoint,
1375 LogicalOperation opcodePacked);
1376 } // namespace gl
1377
1378 #endif // LIBANGLE_VALIDATION_ES_H_
1379