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