• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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