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