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