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 bool ValidateDrawInstancedEXT(const Context *context);
394
395 bool ValidateFramebufferTextureBase(const Context *context,
396 GLenum target,
397 GLenum attachment,
398 TextureID texture,
399 GLint level);
400
401 bool ValidateGetUniformBase(const Context *context,
402 ShaderProgramID program,
403 UniformLocation location);
404 bool ValidateGetnUniformfvEXT(const Context *context,
405 ShaderProgramID program,
406 UniformLocation location,
407 GLsizei bufSize,
408 const GLfloat *params);
409 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
410 ShaderProgramID program,
411 UniformLocation location,
412 GLsizei bufSize,
413 const GLsizei *length,
414 const GLfloat *params);
415 bool ValidateGetnUniformivEXT(const Context *context,
416 ShaderProgramID program,
417 UniformLocation location,
418 GLsizei bufSize,
419 const GLint *params);
420 bool ValidateGetnUniformivRobustANGLE(const Context *context,
421 ShaderProgramID program,
422 UniformLocation location,
423 GLsizei bufSize,
424 const GLsizei *length,
425 const GLint *params);
426 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
427 ShaderProgramID program,
428 UniformLocation location,
429 GLsizei bufSize,
430 const GLsizei *length,
431 const GLuint *params);
432 bool ValidateGetUniformfvRobustANGLE(const Context *context,
433 ShaderProgramID program,
434 UniformLocation location,
435 GLsizei bufSize,
436 const GLsizei *length,
437 const GLfloat *params);
438 bool ValidateGetUniformivRobustANGLE(const Context *context,
439 ShaderProgramID program,
440 UniformLocation location,
441 GLsizei bufSize,
442 const GLsizei *length,
443 const GLint *params);
444 bool ValidateGetUniformuivRobustANGLE(const Context *context,
445 ShaderProgramID program,
446 UniformLocation location,
447 GLsizei bufSize,
448 const GLsizei *length,
449 const GLuint *params);
450
451 bool ValidateDiscardFramebufferBase(const Context *context,
452 GLenum target,
453 GLsizei numAttachments,
454 const GLenum *attachments,
455 bool defaultFramebuffer);
456
457 bool ValidateInsertEventMarkerEXT(const Context *context, GLsizei length, const char *marker);
458 bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker);
459
460 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
461 TextureType type,
462 GLeglImageOES image);
463 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
464 GLenum target,
465 GLeglImageOES image);
466
467 bool ValidateBindVertexArrayBase(const Context *context, VertexArrayID array);
468
469 bool ValidateProgramBinaryBase(const Context *context,
470 ShaderProgramID program,
471 GLenum binaryFormat,
472 const void *binary,
473 GLint length);
474 bool ValidateGetProgramBinaryBase(const Context *context,
475 ShaderProgramID program,
476 GLsizei bufSize,
477 const GLsizei *length,
478 const GLenum *binaryFormat,
479 const void *binary);
480
481 bool ValidateDrawBuffersBase(const Context *context, GLsizei n, const GLenum *bufs);
482
483 bool ValidateGetBufferPointervBase(const Context *context,
484 BufferBinding target,
485 GLenum pname,
486 GLsizei *length,
487 void *const *params);
488 bool ValidateUnmapBufferBase(const Context *context, BufferBinding target);
489 bool ValidateMapBufferRangeBase(const Context *context,
490 BufferBinding target,
491 GLintptr offset,
492 GLsizeiptr length,
493 GLbitfield access);
494 bool ValidateFlushMappedBufferRangeBase(const Context *context,
495 BufferBinding target,
496 GLintptr offset,
497 GLsizeiptr length);
498
499 bool ValidateGenOrDelete(const Context *context, GLint n);
500
501 bool ValidateRobustEntryPoint(const Context *context, GLsizei bufSize);
502 bool ValidateRobustBufferSize(const Context *context, GLsizei bufSize, GLsizei numParams);
503
504 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
505 GLenum target,
506 GLenum attachment,
507 GLenum pname,
508 GLsizei *numParams);
509
510 bool ValidateGetBufferParameterBase(const Context *context,
511 BufferBinding target,
512 GLenum pname,
513 bool pointerVersion,
514 GLsizei *numParams);
515
516 bool ValidateGetProgramivBase(const Context *context,
517 ShaderProgramID program,
518 GLenum pname,
519 GLsizei *numParams);
520
521 bool ValidateGetRenderbufferParameterivBase(const Context *context,
522 GLenum target,
523 GLenum pname,
524 GLsizei *length);
525
526 bool ValidateGetShaderivBase(const Context *context,
527 ShaderProgramID shader,
528 GLenum pname,
529 GLsizei *length);
530
531 bool ValidateGetTexParameterBase(const Context *context,
532 TextureType target,
533 GLenum pname,
534 GLsizei *length);
535
536 template <typename ParamType>
537 bool ValidateTexParameterBase(const Context *context,
538 TextureType target,
539 GLenum pname,
540 GLsizei bufSize,
541 bool vectorParams,
542 const ParamType *params);
543
544 bool ValidateGetVertexAttribBase(const Context *context,
545 GLuint index,
546 GLenum pname,
547 GLsizei *length,
548 bool pointer,
549 bool pureIntegerEntryPoint);
550
ValidateVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribTypeCase validation)551 ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
552 GLuint index,
553 GLint size,
554 VertexAttribTypeCase validation)
555 {
556 const Caps &caps = context->getCaps();
557 if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
558 {
559 context->validationError(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
560 return false;
561 }
562
563 switch (validation)
564 {
565 case VertexAttribTypeCase::Invalid:
566 context->validationError(GL_INVALID_ENUM, err::kInvalidType);
567 return false;
568 case VertexAttribTypeCase::Valid:
569 if (size < 1 || size > 4)
570 {
571 context->validationError(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
572 return false;
573 }
574 break;
575 case VertexAttribTypeCase::ValidSize4Only:
576 if (size != 4)
577 {
578 context->validationError(GL_INVALID_OPERATION,
579 err::kInvalidVertexAttribSize2101010);
580 return false;
581 }
582 break;
583 case VertexAttribTypeCase::ValidSize3or4:
584 if (size != 3 && size != 4)
585 {
586 context->validationError(GL_INVALID_OPERATION,
587 err::kInvalidVertexAttribSize1010102);
588 return false;
589 }
590 break;
591 }
592
593 return true;
594 }
595
596 // 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)597 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
598 GLuint index,
599 GLint size,
600 VertexAttribType type)
601 {
602 return ValidateVertexFormat(context, index, size,
603 context->getStateCache().getVertexAttribTypeValidation(type));
604 }
605
ValidateIntegerVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribType type)606 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
607 GLuint index,
608 GLint size,
609 VertexAttribType type)
610 {
611 return ValidateVertexFormat(
612 context, index, size, context->getStateCache().getIntegerVertexAttribTypeValidation(type));
613 }
614
615 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
616 GLint drawbuffer,
617 const GLenum *validComponentTypes,
618 size_t validComponentTypeCount);
619
620 bool ValidateRobustCompressedTexImageBase(const Context *context,
621 GLsizei imageSize,
622 GLsizei dataSize);
623
624 bool ValidateVertexAttribIndex(const Context *context, GLuint index);
625
626 bool ValidateGetActiveUniformBlockivBase(const Context *context,
627 ShaderProgramID program,
628 GLuint uniformBlockIndex,
629 GLenum pname,
630 GLsizei *length);
631
632 bool ValidateGetSamplerParameterBase(const Context *context,
633 SamplerID sampler,
634 GLenum pname,
635 GLsizei *length);
636
637 template <typename ParamType>
638 bool ValidateSamplerParameterBase(const Context *context,
639 SamplerID sampler,
640 GLenum pname,
641 GLsizei bufSize,
642 bool vectorParams,
643 const ParamType *params);
644
645 bool ValidateGetInternalFormativBase(const Context *context,
646 GLenum target,
647 GLenum internalformat,
648 GLenum pname,
649 GLsizei bufSize,
650 GLsizei *numParams);
651
652 bool ValidateFramebufferNotMultisampled(const Context *context,
653 const Framebuffer *framebuffer,
654 bool needResourceSamples);
655
656 bool ValidateMultitextureUnit(const Context *context, GLenum texture);
657
658 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
659 PrimitiveMode transformFeedbackPrimitiveMode,
660 PrimitiveMode renderPrimitiveMode);
661
662 // Common validation for 2D and 3D variants of TexStorage*Multisample.
663 bool ValidateTexStorageMultisample(const Context *context,
664 TextureType target,
665 GLsizei samples,
666 GLint internalFormat,
667 GLsizei width,
668 GLsizei height);
669
670 bool ValidateTexStorage2DMultisampleBase(const Context *context,
671 TextureType target,
672 GLsizei samples,
673 GLint internalFormat,
674 GLsizei width,
675 GLsizei height);
676
677 bool ValidateGetTexLevelParameterBase(const Context *context,
678 TextureTarget target,
679 GLint level,
680 GLenum pname,
681 GLsizei *length);
682
683 bool ValidateMapBufferBase(const Context *context, BufferBinding target);
684 bool ValidateIndexedStateQuery(const Context *context, GLenum pname, GLuint index, GLsizei *length);
685 bool ValidateES3TexImage2DParameters(const Context *context,
686 TextureTarget target,
687 GLint level,
688 GLenum internalformat,
689 bool isCompressed,
690 bool isSubImage,
691 GLint xoffset,
692 GLint yoffset,
693 GLint zoffset,
694 GLsizei width,
695 GLsizei height,
696 GLsizei depth,
697 GLint border,
698 GLenum format,
699 GLenum type,
700 GLsizei imageSize,
701 const void *pixels);
702 bool ValidateES3CopyTexImage2DParameters(const Context *context,
703 TextureTarget target,
704 GLint level,
705 GLenum internalformat,
706 bool isSubImage,
707 GLint xoffset,
708 GLint yoffset,
709 GLint zoffset,
710 GLint x,
711 GLint y,
712 GLsizei width,
713 GLsizei height,
714 GLint border);
715 bool ValidateES3TexStorage2DParameters(const Context *context,
716 TextureType target,
717 GLsizei levels,
718 GLenum internalformat,
719 GLsizei width,
720 GLsizei height,
721 GLsizei depth);
722 bool ValidateES3TexStorage3DParameters(const Context *context,
723 TextureType target,
724 GLsizei levels,
725 GLenum internalformat,
726 GLsizei width,
727 GLsizei height,
728 GLsizei depth);
729
730 bool ValidateGetMultisamplefvBase(const Context *context,
731 GLenum pname,
732 GLuint index,
733 const GLfloat *val);
734 bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask);
735
736 // Utility macro for handling implementation methods inside Validation.
737 #define ANGLE_HANDLE_VALIDATION_ERR(X) \
738 (void)(X); \
739 return false
740 #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR)
741
742 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
743 // implementation format info for incomplete framebuffers. It seems like these queries are
744 // incongruent with the other errors.
745 // Inlined for speed.
746 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,const Framebuffer * framebuffer)747 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
748 const Framebuffer *framebuffer)
749 {
750 if (!framebuffer->isComplete(context))
751 {
752 context->validationError(ErrorCode, err::kFramebufferIncomplete);
753 return false;
754 }
755
756 return true;
757 }
758
759 const char *ValidateProgramDrawStates(const State &state,
760 const Extensions &extensions,
761 Program *program);
762 const char *ValidateProgramPipelineDrawStates(const State &state,
763 const Extensions &extensions,
764 ProgramPipeline *programPipeline);
765 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
766 const char *ValidateDrawStates(const Context *context);
767
768 void RecordDrawAttribsError(const Context *context);
769
ValidateDrawAttribs(const Context * context,int64_t maxVertex)770 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context, int64_t maxVertex)
771 {
772 if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit())
773 {
774 RecordDrawAttribsError(context);
775 return false;
776 }
777
778 return true;
779 }
780
ValidateDrawArraysAttribs(const Context * context,GLint first,GLsizei count)781 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context, GLint first, GLsizei count)
782 {
783 if (!context->isBufferAccessValidationEnabled())
784 {
785 return true;
786 }
787
788 // Check the computation of maxVertex doesn't overflow.
789 // - first < 0 has been checked as an error condition.
790 // - if count <= 0, skip validating no-op draw calls.
791 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
792 ASSERT(first >= 0);
793 ASSERT(count > 0);
794 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
795 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
796 {
797 context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
798 return false;
799 }
800
801 return ValidateDrawAttribs(context, maxVertex);
802 }
803
ValidateDrawInstancedAttribs(const Context * context,GLint primcount)804 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, GLint primcount)
805 {
806 if (!context->isBufferAccessValidationEnabled())
807 {
808 return true;
809 }
810
811 if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit())
812 {
813 RecordDrawAttribsError(context);
814 return false;
815 }
816
817 return true;
818 }
819
ValidateDrawArraysCommon(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)820 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
821 PrimitiveMode mode,
822 GLint first,
823 GLsizei count,
824 GLsizei primcount)
825 {
826 if (first < 0)
827 {
828 context->validationError(GL_INVALID_VALUE, err::kNegativeStart);
829 return false;
830 }
831
832 if (count <= 0)
833 {
834 if (count < 0)
835 {
836 context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
837 return false;
838 }
839
840 // Early exit.
841 return ValidateDrawBase(context, mode);
842 }
843
844 if (!ValidateDrawBase(context, mode))
845 {
846 return false;
847 }
848
849 if (context->getStateCache().isTransformFeedbackActiveUnpaused())
850 {
851 const State &state = context->getState();
852 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
853 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
854 {
855 context->validationError(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
856 return false;
857 }
858 }
859
860 return ValidateDrawArraysAttribs(context, first, count);
861 }
862
ValidateDrawElementsBase(const Context * context,PrimitiveMode mode,DrawElementsType type)863 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
864 PrimitiveMode mode,
865 DrawElementsType type)
866 {
867 if (!context->getStateCache().isValidDrawElementsType(type))
868 {
869 if (type == DrawElementsType::UnsignedInt)
870 {
871 context->validationError(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
872 return false;
873 }
874
875 ASSERT(type == DrawElementsType::InvalidEnum);
876 context->validationError(GL_INVALID_ENUM, err::kEnumNotSupported);
877 return false;
878 }
879
880 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
881 if (drawElementsError)
882 {
883 // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
884 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
885 context->validationError(GL_INVALID_OPERATION, errorMessage);
886 return false;
887 }
888
889 // Note that we are missing overflow checks for active transform feedback buffers.
890 return true;
891 }
892
ValidateDrawElementsCommon(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)893 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
894 PrimitiveMode mode,
895 GLsizei count,
896 DrawElementsType type,
897 const void *indices,
898 GLsizei primcount)
899 {
900 if (!ValidateDrawElementsBase(context, mode, type))
901 {
902 return false;
903 }
904
905 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
906
907 if (context->getExtensions().webglCompatibility)
908 {
909 GLuint typeBytes = GetDrawElementsTypeSize(type);
910
911 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
912 {
913 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
914 // The offset arguments to drawElements and [...], must be a multiple of the size of the
915 // data type passed to the call, or an INVALID_OPERATION error is generated.
916 context->validationError(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
917 return false;
918 }
919
920 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
921 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
922 // error is generated.
923 if (reinterpret_cast<intptr_t>(indices) < 0)
924 {
925 context->validationError(GL_INVALID_VALUE, err::kNegativeOffset);
926 return false;
927 }
928 }
929
930 if (count <= 0)
931 {
932 if (count < 0)
933 {
934 context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
935 return false;
936 }
937
938 // Early exit.
939 return ValidateDrawBase(context, mode);
940 }
941
942 if (!ValidateDrawBase(context, mode))
943 {
944 return false;
945 }
946
947 const State &state = context->getState();
948 const VertexArray *vao = state.getVertexArray();
949 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
950
951 if (!elementArrayBuffer)
952 {
953 if (!indices)
954 {
955 // This is an application error that would normally result in a crash, but we catch
956 // it and return an error
957 context->validationError(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
958 return false;
959 }
960 }
961 else
962 {
963 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
964 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
965 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
966 constexpr uint64_t kMaxTypeSize = 8;
967 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
968 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
969 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
970
971 uint64_t elementCount = static_cast<uint64_t>(count);
972 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
973
974 // Doing the multiplication here is overflow-safe
975 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
976
977 // The offset can be any value, check for overflows
978 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
979 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
980 if (elementDataSizeWithOffset < elementDataSizeNoOffset)
981 {
982 context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
983 return false;
984 }
985
986 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
987 {
988 context->validationError(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
989 return false;
990 }
991 }
992
993 if (context->isBufferAccessValidationEnabled() && primcount > 0)
994 {
995 // Use the parameter buffer to retrieve and cache the index range.
996 IndexRange indexRange{IndexRange::Undefined()};
997 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
998
999 // If we use an index greater than our maximum supported index range, return an error.
1000 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1001 // always return an error if possible here.
1002 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1003 {
1004 context->validationError(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1005 return false;
1006 }
1007
1008 if (!ValidateDrawAttribs(context, static_cast<GLint>(indexRange.end)))
1009 {
1010 return false;
1011 }
1012
1013 // No op if there are no real indices in the index data (all are primitive restart).
1014 return (indexRange.vertexIndexCount > 0);
1015 }
1016
1017 return true;
1018 }
1019 } // namespace gl
1020
1021 #endif // LIBANGLE_VALIDATION_ES_H_
1022