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