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 void SetRobustLengthParam(const GLsizei *length, GLsizei value);
40 bool ValidTextureTarget(const Context *context, TextureType type);
41 bool ValidTexture2DTarget(const Context *context, TextureType type);
42 bool ValidTexture3DTarget(const Context *context, TextureType target);
43 bool ValidTextureExternalTarget(const Context *context, TextureType target);
44 bool ValidTextureExternalTarget(const Context *context, TextureTarget target);
45 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target);
46 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target);
47 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type);
48 bool ValidFramebufferTarget(const Context *context, GLenum target);
49 bool ValidMipLevel(const Context *context, TextureType type, GLint level);
50 bool ValidImageSizeParameters(const Context *context,
51 TextureType target,
52 GLint level,
53 GLsizei width,
54 GLsizei height,
55 GLsizei depth,
56 bool isSubImage);
57 bool ValidCompressedImageSize(const Context *context,
58 GLenum internalFormat,
59 GLint level,
60 GLsizei width,
61 GLsizei height,
62 GLsizei depth);
63 bool ValidCompressedSubImageSize(const Context *context,
64 GLenum internalFormat,
65 GLint xoffset,
66 GLint yoffset,
67 GLint zoffset,
68 GLsizei width,
69 GLsizei height,
70 GLsizei depth,
71 size_t textureWidth,
72 size_t textureHeight,
73 size_t textureDepth);
74 bool ValidImageDataSize(const Context *context,
75 TextureType texType,
76 GLsizei width,
77 GLsizei height,
78 GLsizei depth,
79 GLenum format,
80 GLenum type,
81 const void *pixels,
82 GLsizei imageSize);
83
84 bool ValidQueryType(const Context *context, QueryType queryType);
85
86 bool ValidateWebGLVertexAttribPointer(const Context *context,
87 VertexAttribType type,
88 GLboolean normalized,
89 GLsizei stride,
90 const void *ptr,
91 bool pureInteger);
92
93 // Returns valid program if id is a valid program name
94 // Errors INVALID_OPERATION if valid shader is given and returns NULL
95 // Errors INVALID_VALUE otherwise and returns NULL
96 Program *GetValidProgram(const Context *context, ShaderProgramID id);
97
98 // Returns valid shader if id is a valid shader name
99 // Errors INVALID_OPERATION if valid program is given and returns NULL
100 // Errors INVALID_VALUE otherwise and returns NULL
101 Shader *GetValidShader(const Context *context, ShaderProgramID id);
102
103 bool ValidateAttachmentTarget(const Context *context, GLenum attachment);
104
105 bool ValidateBlitFramebufferParameters(const Context *context,
106 GLint srcX0,
107 GLint srcY0,
108 GLint srcX1,
109 GLint srcY1,
110 GLint dstX0,
111 GLint dstY0,
112 GLint dstX1,
113 GLint dstY1,
114 GLbitfield mask,
115 GLenum filter);
116
117 bool ValidateBindFramebufferBase(const Context *context, GLenum target, FramebufferID framebuffer);
118 bool ValidateBindRenderbufferBase(const Context *context,
119 GLenum target,
120 RenderbufferID renderbuffer);
121 bool ValidateFramebufferRenderbufferBase(const Context *context,
122 GLenum target,
123 GLenum attachment,
124 GLenum renderbuffertarget,
125 RenderbufferID renderbuffer);
126 bool ValidateFramebufferTextureBase(const Context *context,
127 GLenum target,
128 GLenum attachment,
129 TextureID texture,
130 GLint level);
131 bool ValidateGenerateMipmapBase(const Context *context, TextureType target);
132
133 bool ValidateRenderbufferStorageParametersBase(const Context *context,
134 GLenum target,
135 GLsizei samples,
136 GLenum internalformat,
137 GLsizei width,
138 GLsizei height);
139
140 bool ValidatePixelPack(const Context *context,
141 GLenum format,
142 GLenum type,
143 GLint x,
144 GLint y,
145 GLsizei width,
146 GLsizei height,
147 GLsizei bufSize,
148 GLsizei *length,
149 const void *pixels);
150
151 bool ValidateReadPixelsBase(const Context *context,
152 GLint x,
153 GLint y,
154 GLsizei width,
155 GLsizei height,
156 GLenum format,
157 GLenum type,
158 GLsizei bufSize,
159 GLsizei *length,
160 GLsizei *columns,
161 GLsizei *rows,
162 const void *pixels);
163 bool ValidateReadPixelsRobustANGLE(const Context *context,
164 GLint x,
165 GLint y,
166 GLsizei width,
167 GLsizei height,
168 GLenum format,
169 GLenum type,
170 GLsizei bufSize,
171 const GLsizei *length,
172 const GLsizei *columns,
173 const GLsizei *rows,
174 const void *pixels);
175 bool ValidateReadnPixelsEXT(const Context *context,
176 GLint x,
177 GLint y,
178 GLsizei width,
179 GLsizei height,
180 GLenum format,
181 GLenum type,
182 GLsizei bufSize,
183 const void *pixels);
184 bool ValidateReadnPixelsRobustANGLE(const Context *context,
185 GLint x,
186 GLint y,
187 GLsizei width,
188 GLsizei height,
189 GLenum format,
190 GLenum type,
191 GLsizei bufSize,
192 const GLsizei *length,
193 const GLsizei *columns,
194 const GLsizei *rows,
195 const void *data);
196
197 bool ValidateGenQueriesEXT(const Context *context, GLsizei n, const QueryID *ids);
198 bool ValidateDeleteQueriesEXT(const Context *context, GLsizei n, const QueryID *ids);
199 bool ValidateIsQueryEXT(const Context *context, QueryID id);
200 bool ValidateBeginQueryBase(const Context *context, QueryType target, QueryID id);
201 bool ValidateBeginQueryEXT(const Context *context, QueryType target, QueryID id);
202 bool ValidateEndQueryBase(const Context *context, QueryType target);
203 bool ValidateEndQueryEXT(const Context *context, QueryType target);
204 bool ValidateQueryCounterEXT(const Context *context, QueryID id, QueryType target);
205 bool ValidateGetQueryivBase(const Context *context,
206 QueryType target,
207 GLenum pname,
208 GLsizei *numParams);
209 bool ValidateGetQueryivEXT(const Context *context,
210 QueryType target,
211 GLenum pname,
212 const GLint *params);
213 bool ValidateGetQueryivRobustANGLE(const Context *context,
214 QueryType target,
215 GLenum pname,
216 GLsizei bufSize,
217 const GLsizei *length,
218 const GLint *params);
219 bool ValidateGetQueryObjectValueBase(const Context *context,
220 QueryID id,
221 GLenum pname,
222 GLsizei *numParams);
223 bool ValidateGetQueryObjectivEXT(const Context *context,
224 QueryID id,
225 GLenum pname,
226 const GLint *params);
227 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
228 QueryID id,
229 GLenum pname,
230 GLsizei bufSize,
231 const GLsizei *length,
232 const GLint *params);
233 bool ValidateGetQueryObjectuivEXT(const Context *context,
234 QueryID id,
235 GLenum pname,
236 const GLuint *params);
237 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
238 QueryID id,
239 GLenum pname,
240 GLsizei bufSize,
241 const GLsizei *length,
242 const GLuint *params);
243 bool ValidateGetQueryObjecti64vEXT(const Context *context,
244 QueryID id,
245 GLenum pname,
246 GLint64 *params);
247 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
248 QueryID id,
249 GLenum pname,
250 GLsizei bufSize,
251 const GLsizei *length,
252 GLint64 *params);
253 bool ValidateGetQueryObjectui64vEXT(const Context *context,
254 QueryID id,
255 GLenum pname,
256 GLuint64 *params);
257 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
258 QueryID id,
259 GLenum pname,
260 GLsizei bufSize,
261 const GLsizei *length,
262 GLuint64 *params);
263
264 bool ValidateUniformCommonBase(const Context *context,
265 const Program *program,
266 UniformLocation location,
267 GLsizei count,
268 const LinkedUniform **uniformOut);
269 bool ValidateUniform1ivValue(const Context *context,
270 GLenum uniformType,
271 GLsizei count,
272 const GLint *value);
273
ValidateUniformValue(const Context * context,GLenum valueType,GLenum uniformType)274 ANGLE_INLINE bool ValidateUniformValue(const Context *context, GLenum valueType, GLenum uniformType)
275 {
276 // Check that the value type is compatible with uniform type.
277 // Do the cheaper test first, for a little extra speed.
278 if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
279 {
280 context->validationError(GL_INVALID_OPERATION, err::kUniformSizeMismatch);
281 return false;
282 }
283 return true;
284 }
285
286 bool ValidateUniformMatrixValue(const Context *context, GLenum valueType, GLenum uniformType);
287 bool ValidateUniform(const Context *context,
288 GLenum uniformType,
289 UniformLocation location,
290 GLsizei count);
291 bool ValidateUniformMatrix(const Context *context,
292 GLenum matrixType,
293 UniformLocation location,
294 GLsizei count,
295 GLboolean transpose);
296 bool ValidateGetBooleanvRobustANGLE(const Context *context,
297 GLenum pname,
298 GLsizei bufSize,
299 const GLsizei *length,
300 const GLboolean *params);
301 bool ValidateGetFloatvRobustANGLE(const Context *context,
302 GLenum pname,
303 GLsizei bufSize,
304 const GLsizei *length,
305 const GLfloat *params);
306 bool ValidateStateQuery(const Context *context,
307 GLenum pname,
308 GLenum *nativeType,
309 unsigned int *numParams);
310 bool ValidateGetIntegervRobustANGLE(const Context *context,
311 GLenum pname,
312 GLsizei bufSize,
313 const GLsizei *length,
314 const GLint *data);
315 bool ValidateGetInteger64vRobustANGLE(const Context *context,
316 GLenum pname,
317 GLsizei bufSize,
318 const GLsizei *length,
319 GLint64 *data);
320 bool ValidateRobustStateQuery(const Context *context,
321 GLenum pname,
322 GLsizei bufSize,
323 GLenum *nativeType,
324 unsigned int *numParams);
325
326 bool ValidateCopyImageSubDataBase(const Context *context,
327 GLuint srcName,
328 GLenum srcTarget,
329 GLint srcLevel,
330 GLint srcX,
331 GLint srcY,
332 GLint srcZ,
333 GLuint dstName,
334 GLenum dstTarget,
335 GLint dstLevel,
336 GLint dstX,
337 GLint dstY,
338 GLint dstZ,
339 GLsizei srcWidth,
340 GLsizei srcHeight,
341 GLsizei srcDepth);
342
343 bool ValidateCopyTexImageParametersBase(const Context *context,
344 TextureTarget target,
345 GLint level,
346 GLenum internalformat,
347 bool isSubImage,
348 GLint xoffset,
349 GLint yoffset,
350 GLint zoffset,
351 GLint x,
352 GLint y,
353 GLsizei width,
354 GLsizei height,
355 GLint border,
356 Format *textureFormatOut);
357
358 void RecordDrawModeError(const Context *context, PrimitiveMode mode);
359 const char *ValidateDrawElementsStates(const Context *context);
360
ValidateDrawBase(const Context * context,PrimitiveMode mode)361 ANGLE_INLINE bool ValidateDrawBase(const Context *context, PrimitiveMode mode)
362 {
363 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
364 if (drawStatesError)
365 {
366 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
367
368 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
369 // Incomplete.
370 bool isFramebufferIncomplete = strcmp(errorMessage, err::kDrawFramebufferIncomplete) == 0;
371 GLenum errorCode =
372 isFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION : GL_INVALID_OPERATION;
373 context->validationError(errorCode, errorMessage);
374 return false;
375 }
376
377 if (!context->getStateCache().isValidDrawMode(mode))
378 {
379 RecordDrawModeError(context, mode);
380 return false;
381 }
382
383 return true;
384 }
385
386 bool ValidateDrawArraysInstancedBase(const Context *context,
387 PrimitiveMode mode,
388 GLint first,
389 GLsizei count,
390 GLsizei primcount);
391 bool ValidateDrawArraysInstancedANGLE(const Context *context,
392 PrimitiveMode mode,
393 GLint first,
394 GLsizei count,
395 GLsizei primcount);
396 bool ValidateDrawArraysInstancedEXT(const Context *context,
397 PrimitiveMode mode,
398 GLint first,
399 GLsizei count,
400 GLsizei primcount);
401
402 bool ValidateDrawElementsInstancedBase(const Context *context,
403 PrimitiveMode mode,
404 GLsizei count,
405 DrawElementsType type,
406 const void *indices,
407 GLsizei primcount);
408 bool ValidateDrawElementsInstancedANGLE(const Context *context,
409 PrimitiveMode mode,
410 GLsizei count,
411 DrawElementsType type,
412 const void *indices,
413 GLsizei primcount);
414 bool ValidateDrawElementsInstancedEXT(const Context *context,
415 PrimitiveMode mode,
416 GLsizei count,
417 DrawElementsType type,
418 const void *indices,
419 GLsizei primcount);
420
421 bool ValidateDrawInstancedANGLE(const Context *context);
422
423 bool ValidateGetUniformBase(const Context *context,
424 ShaderProgramID program,
425 UniformLocation location);
426 bool ValidateGetnUniformfvEXT(const Context *context,
427 ShaderProgramID program,
428 UniformLocation location,
429 GLsizei bufSize,
430 const GLfloat *params);
431 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
432 ShaderProgramID program,
433 UniformLocation location,
434 GLsizei bufSize,
435 const GLsizei *length,
436 const GLfloat *params);
437 bool ValidateGetnUniformivEXT(const Context *context,
438 ShaderProgramID program,
439 UniformLocation location,
440 GLsizei bufSize,
441 const GLint *params);
442 bool ValidateGetnUniformivRobustANGLE(const Context *context,
443 ShaderProgramID program,
444 UniformLocation location,
445 GLsizei bufSize,
446 const GLsizei *length,
447 const GLint *params);
448 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
449 ShaderProgramID program,
450 UniformLocation location,
451 GLsizei bufSize,
452 const GLsizei *length,
453 const GLuint *params);
454 bool ValidateGetUniformfvRobustANGLE(const Context *context,
455 ShaderProgramID program,
456 UniformLocation location,
457 GLsizei bufSize,
458 const GLsizei *length,
459 const GLfloat *params);
460 bool ValidateGetUniformivRobustANGLE(const Context *context,
461 ShaderProgramID program,
462 UniformLocation location,
463 GLsizei bufSize,
464 const GLsizei *length,
465 const GLint *params);
466 bool ValidateGetUniformuivRobustANGLE(const Context *context,
467 ShaderProgramID program,
468 UniformLocation location,
469 GLsizei bufSize,
470 const GLsizei *length,
471 const GLuint *params);
472
473 bool ValidateDiscardFramebufferBase(const Context *context,
474 GLenum target,
475 GLsizei numAttachments,
476 const GLenum *attachments,
477 bool defaultFramebuffer);
478
479 bool ValidateInsertEventMarkerEXT(const Context *context, GLsizei length, const char *marker);
480 bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker);
481
482 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
483 TextureType type,
484 GLeglImageOES image);
485 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
486 GLenum target,
487 GLeglImageOES image);
488
489 bool ValidateBindVertexArrayBase(const Context *context, VertexArrayID array);
490
491 bool ValidateProgramBinaryBase(const Context *context,
492 ShaderProgramID program,
493 GLenum binaryFormat,
494 const void *binary,
495 GLint length);
496 bool ValidateGetProgramBinaryBase(const Context *context,
497 ShaderProgramID program,
498 GLsizei bufSize,
499 const GLsizei *length,
500 const GLenum *binaryFormat,
501 const void *binary);
502
503 bool ValidateDrawBuffersBase(const Context *context, GLsizei n, const GLenum *bufs);
504
505 bool ValidateGetBufferPointervBase(const Context *context,
506 BufferBinding target,
507 GLenum pname,
508 GLsizei *length,
509 void *const *params);
510 bool ValidateUnmapBufferBase(const Context *context, BufferBinding target);
511 bool ValidateMapBufferRangeBase(const Context *context,
512 BufferBinding target,
513 GLintptr offset,
514 GLsizeiptr length,
515 GLbitfield access);
516 bool ValidateFlushMappedBufferRangeBase(const Context *context,
517 BufferBinding target,
518 GLintptr offset,
519 GLsizeiptr length);
520
521 bool ValidateGenOrDelete(const Context *context, GLint n);
522
523 bool ValidateRobustEntryPoint(const Context *context, GLsizei bufSize);
524 bool ValidateRobustBufferSize(const Context *context, GLsizei bufSize, GLsizei numParams);
525
526 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
527 GLenum target,
528 GLenum attachment,
529 GLenum pname,
530 GLsizei *numParams);
531
532 bool ValidateGetBufferParameterBase(const Context *context,
533 BufferBinding target,
534 GLenum pname,
535 bool pointerVersion,
536 GLsizei *numParams);
537
538 bool ValidateGetProgramivBase(const Context *context,
539 ShaderProgramID program,
540 GLenum pname,
541 GLsizei *numParams);
542
543 bool ValidateGetRenderbufferParameterivBase(const Context *context,
544 GLenum target,
545 GLenum pname,
546 GLsizei *length);
547
548 bool ValidateGetShaderivBase(const Context *context,
549 ShaderProgramID shader,
550 GLenum pname,
551 GLsizei *length);
552
553 bool ValidateGetTexParameterBase(const Context *context,
554 TextureType target,
555 GLenum pname,
556 GLsizei *length);
557
558 template <typename ParamType>
559 bool ValidateTexParameterBase(const Context *context,
560 TextureType target,
561 GLenum pname,
562 GLsizei bufSize,
563 bool vectorParams,
564 const ParamType *params);
565
566 bool ValidateGetVertexAttribBase(const Context *context,
567 GLuint index,
568 GLenum pname,
569 GLsizei *length,
570 bool pointer,
571 bool pureIntegerEntryPoint);
572
ValidateVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribTypeCase validation)573 ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
574 GLuint index,
575 GLint size,
576 VertexAttribTypeCase validation)
577 {
578 const Caps &caps = context->getCaps();
579 if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
580 {
581 context->validationError(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
582 return false;
583 }
584
585 switch (validation)
586 {
587 case VertexAttribTypeCase::Invalid:
588 context->validationError(GL_INVALID_ENUM, err::kInvalidType);
589 return false;
590 case VertexAttribTypeCase::Valid:
591 if (size < 1 || size > 4)
592 {
593 context->validationError(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
594 return false;
595 }
596 break;
597 case VertexAttribTypeCase::ValidSize4Only:
598 if (size != 4)
599 {
600 context->validationError(GL_INVALID_OPERATION,
601 err::kInvalidVertexAttribSize2101010);
602 return false;
603 }
604 break;
605 case VertexAttribTypeCase::ValidSize3or4:
606 if (size != 3 && size != 4)
607 {
608 context->validationError(GL_INVALID_OPERATION,
609 err::kInvalidVertexAttribSize1010102);
610 return false;
611 }
612 break;
613 }
614
615 return true;
616 }
617
618 // Note: These byte, short, and int types are all converted to float for the shader.
ValidateFloatVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribType type)619 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
620 GLuint index,
621 GLint size,
622 VertexAttribType type)
623 {
624 return ValidateVertexFormat(context, index, size,
625 context->getStateCache().getVertexAttribTypeValidation(type));
626 }
627
ValidateIntegerVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribType type)628 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
629 GLuint index,
630 GLint size,
631 VertexAttribType type)
632 {
633 return ValidateVertexFormat(
634 context, index, size, context->getStateCache().getIntegerVertexAttribTypeValidation(type));
635 }
636
637 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
638 GLint drawbuffer,
639 const GLenum *validComponentTypes,
640 size_t validComponentTypeCount);
641
642 bool ValidateRobustCompressedTexImageBase(const Context *context,
643 GLsizei imageSize,
644 GLsizei dataSize);
645
646 bool ValidateVertexAttribIndex(const Context *context, GLuint index);
647
648 bool ValidateGetActiveUniformBlockivBase(const Context *context,
649 ShaderProgramID program,
650 UniformBlockIndex uniformBlockIndex,
651 GLenum pname,
652 GLsizei *length);
653
654 bool ValidateGetSamplerParameterBase(const Context *context,
655 SamplerID sampler,
656 GLenum pname,
657 GLsizei *length);
658
659 template <typename ParamType>
660 bool ValidateSamplerParameterBase(const Context *context,
661 SamplerID sampler,
662 GLenum pname,
663 GLsizei bufSize,
664 bool vectorParams,
665 const ParamType *params);
666
667 bool ValidateGetInternalFormativBase(const Context *context,
668 GLenum target,
669 GLenum internalformat,
670 GLenum pname,
671 GLsizei bufSize,
672 GLsizei *numParams);
673
674 bool ValidateFramebufferNotMultisampled(const Context *context,
675 const Framebuffer *framebuffer,
676 bool checkReadBufferResourceSamples);
677
678 bool ValidateMultitextureUnit(const Context *context, GLenum texture);
679
680 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
681 PrimitiveMode transformFeedbackPrimitiveMode,
682 PrimitiveMode renderPrimitiveMode);
683
684 // Common validation for 2D and 3D variants of TexStorage*Multisample.
685 bool ValidateTexStorageMultisample(const Context *context,
686 TextureType target,
687 GLsizei samples,
688 GLint internalFormat,
689 GLsizei width,
690 GLsizei height);
691
692 bool ValidateTexStorage2DMultisampleBase(const Context *context,
693 TextureType target,
694 GLsizei samples,
695 GLint internalFormat,
696 GLsizei width,
697 GLsizei height);
698
699 bool ValidateGetTexLevelParameterBase(const Context *context,
700 TextureTarget target,
701 GLint level,
702 GLenum pname,
703 GLsizei *length);
704
705 bool ValidateMapBufferBase(const Context *context, BufferBinding target);
706 bool ValidateIndexedStateQuery(const Context *context, GLenum pname, GLuint index, GLsizei *length);
707 bool ValidateES3TexImage2DParameters(const Context *context,
708 TextureTarget target,
709 GLint level,
710 GLenum internalformat,
711 bool isCompressed,
712 bool isSubImage,
713 GLint xoffset,
714 GLint yoffset,
715 GLint zoffset,
716 GLsizei width,
717 GLsizei height,
718 GLsizei depth,
719 GLint border,
720 GLenum format,
721 GLenum type,
722 GLsizei imageSize,
723 const void *pixels);
724 bool ValidateES3CopyTexImage2DParameters(const Context *context,
725 TextureTarget target,
726 GLint level,
727 GLenum internalformat,
728 bool isSubImage,
729 GLint xoffset,
730 GLint yoffset,
731 GLint zoffset,
732 GLint x,
733 GLint y,
734 GLsizei width,
735 GLsizei height,
736 GLint border);
737 bool ValidateES3TexStorage2DParameters(const Context *context,
738 TextureType target,
739 GLsizei levels,
740 GLenum internalformat,
741 GLsizei width,
742 GLsizei height,
743 GLsizei depth);
744 bool ValidateES3TexStorage3DParameters(const Context *context,
745 TextureType target,
746 GLsizei levels,
747 GLenum internalformat,
748 GLsizei width,
749 GLsizei height,
750 GLsizei depth);
751
752 bool ValidateGetMultisamplefvBase(const Context *context,
753 GLenum pname,
754 GLuint index,
755 const GLfloat *val);
756 bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask);
757
758 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
759 // implementation format info for incomplete framebuffers. It seems like these queries are
760 // incongruent with the other errors.
761 // Inlined for speed.
762 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,const Framebuffer * framebuffer)763 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
764 const Framebuffer *framebuffer)
765 {
766 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
767 if (!framebufferStatus.isComplete())
768 {
769 ASSERT(framebufferStatus.reason != nullptr);
770 context->validationError(ErrorCode, framebufferStatus.reason);
771 return false;
772 }
773
774 return true;
775 }
776
777 const char *ValidateProgramPipelineDrawStates(const State &state,
778 const Extensions &extensions,
779 ProgramPipeline *programPipeline);
780 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
781 const char *ValidateDrawStates(const Context *context);
782
783 void RecordDrawAttribsError(const Context *context);
784
ValidateDrawAttribs(const Context * context,int64_t maxVertex)785 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context, int64_t maxVertex)
786 {
787 if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit())
788 {
789 RecordDrawAttribsError(context);
790 return false;
791 }
792
793 return true;
794 }
795
ValidateDrawArraysAttribs(const Context * context,GLint first,GLsizei count)796 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context, GLint first, GLsizei count)
797 {
798 if (!context->isBufferAccessValidationEnabled())
799 {
800 return true;
801 }
802
803 // Check the computation of maxVertex doesn't overflow.
804 // - first < 0 has been checked as an error condition.
805 // - if count <= 0, skip validating no-op draw calls.
806 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
807 ASSERT(first >= 0);
808 ASSERT(count > 0);
809 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
810 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
811 {
812 context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
813 return false;
814 }
815
816 return ValidateDrawAttribs(context, maxVertex);
817 }
818
ValidateDrawInstancedAttribs(const Context * context,GLint primcount)819 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, GLint primcount)
820 {
821 if (!context->isBufferAccessValidationEnabled())
822 {
823 return true;
824 }
825
826 if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit())
827 {
828 RecordDrawAttribsError(context);
829 return false;
830 }
831
832 return true;
833 }
834
ValidateDrawArraysCommon(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)835 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
836 PrimitiveMode mode,
837 GLint first,
838 GLsizei count,
839 GLsizei primcount)
840 {
841 if (first < 0)
842 {
843 context->validationError(GL_INVALID_VALUE, err::kNegativeStart);
844 return false;
845 }
846
847 if (count <= 0)
848 {
849 if (count < 0)
850 {
851 context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
852 return false;
853 }
854
855 // Early exit.
856 return ValidateDrawBase(context, mode);
857 }
858
859 if (!ValidateDrawBase(context, mode))
860 {
861 return false;
862 }
863
864 if (context->getStateCache().isTransformFeedbackActiveUnpaused() &&
865 !context->supportsGeometryOrTesselation())
866 {
867 const State &state = context->getState();
868 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
869 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
870 {
871 context->validationError(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
872 return false;
873 }
874 }
875
876 return ValidateDrawArraysAttribs(context, first, count);
877 }
878
ValidateDrawElementsBase(const Context * context,PrimitiveMode mode,DrawElementsType type)879 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
880 PrimitiveMode mode,
881 DrawElementsType type)
882 {
883 if (!context->getStateCache().isValidDrawElementsType(type))
884 {
885 if (type == DrawElementsType::UnsignedInt)
886 {
887 context->validationError(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
888 return false;
889 }
890
891 ASSERT(type == DrawElementsType::InvalidEnum);
892 context->validationError(GL_INVALID_ENUM, err::kEnumNotSupported);
893 return false;
894 }
895
896 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
897 if (drawElementsError)
898 {
899 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
900 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
901 context->validationError(GL_INVALID_OPERATION, errorMessage);
902 return false;
903 }
904
905 // Note that we are missing overflow checks for active transform feedback buffers.
906 return true;
907 }
908
ValidateDrawElementsCommon(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)909 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
910 PrimitiveMode mode,
911 GLsizei count,
912 DrawElementsType type,
913 const void *indices,
914 GLsizei primcount)
915 {
916 if (!ValidateDrawElementsBase(context, mode, type))
917 {
918 return false;
919 }
920
921 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
922
923 if (context->getExtensions().webglCompatibility)
924 {
925 GLuint typeBytes = GetDrawElementsTypeSize(type);
926
927 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
928 {
929 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
930 // The offset arguments to drawElements and [...], must be a multiple of the size of the
931 // data type passed to the call, or an INVALID_OPERATION error is generated.
932 context->validationError(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
933 return false;
934 }
935
936 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
937 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
938 // error is generated.
939 if (reinterpret_cast<intptr_t>(indices) < 0)
940 {
941 context->validationError(GL_INVALID_VALUE, err::kNegativeOffset);
942 return false;
943 }
944 }
945
946 if (count <= 0)
947 {
948 if (count < 0)
949 {
950 context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
951 return false;
952 }
953
954 // Early exit.
955 return ValidateDrawBase(context, mode);
956 }
957
958 if (!ValidateDrawBase(context, mode))
959 {
960 return false;
961 }
962
963 const State &state = context->getState();
964 const VertexArray *vao = state.getVertexArray();
965 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
966
967 if (!elementArrayBuffer)
968 {
969 if (!indices)
970 {
971 // This is an application error that would normally result in a crash, but we catch
972 // it and return an error
973 context->validationError(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
974 return false;
975 }
976 }
977 else
978 {
979 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
980 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
981 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
982 constexpr uint64_t kMaxTypeSize = 8;
983 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
984 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
985 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
986
987 uint64_t elementCount = static_cast<uint64_t>(count);
988 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
989
990 // Doing the multiplication here is overflow-safe
991 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
992
993 // The offset can be any value, check for overflows
994 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
995 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
996 if (elementDataSizeWithOffset < elementDataSizeNoOffset)
997 {
998 context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
999 return false;
1000 }
1001
1002 // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064
1003 if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) &&
1004 (primcount > 0))
1005 {
1006 context->validationError(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
1007 return false;
1008 }
1009 }
1010
1011 if (context->isBufferAccessValidationEnabled() && primcount > 0)
1012 {
1013 // Use the parameter buffer to retrieve and cache the index range.
1014 IndexRange indexRange{IndexRange::Undefined()};
1015 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
1016
1017 // If we use an index greater than our maximum supported index range, return an error.
1018 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1019 // always return an error if possible here.
1020 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1021 {
1022 context->validationError(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1023 return false;
1024 }
1025
1026 if (!ValidateDrawAttribs(context, static_cast<GLint>(indexRange.end)))
1027 {
1028 return false;
1029 }
1030
1031 // No op if there are no real indices in the index data (all are primitive restart).
1032 return (indexRange.vertexIndexCount > 0);
1033 }
1034
1035 return true;
1036 }
1037 } // namespace gl
1038
1039 #endif // LIBANGLE_VALIDATION_ES_H_
1040