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