• 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 bool ValidateDrawInstancedEXT(const Context *context);
394 
395 bool ValidateFramebufferTextureBase(const Context *context,
396                                     GLenum target,
397                                     GLenum attachment,
398                                     TextureID texture,
399                                     GLint level);
400 
401 bool ValidateGetUniformBase(const Context *context,
402                             ShaderProgramID program,
403                             UniformLocation location);
404 bool ValidateGetnUniformfvEXT(const Context *context,
405                               ShaderProgramID program,
406                               UniformLocation location,
407                               GLsizei bufSize,
408                               const GLfloat *params);
409 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
410                                       ShaderProgramID program,
411                                       UniformLocation location,
412                                       GLsizei bufSize,
413                                       const GLsizei *length,
414                                       const GLfloat *params);
415 bool ValidateGetnUniformivEXT(const Context *context,
416                               ShaderProgramID program,
417                               UniformLocation location,
418                               GLsizei bufSize,
419                               const GLint *params);
420 bool ValidateGetnUniformivRobustANGLE(const Context *context,
421                                       ShaderProgramID program,
422                                       UniformLocation location,
423                                       GLsizei bufSize,
424                                       const GLsizei *length,
425                                       const GLint *params);
426 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
427                                        ShaderProgramID program,
428                                        UniformLocation location,
429                                        GLsizei bufSize,
430                                        const GLsizei *length,
431                                        const GLuint *params);
432 bool ValidateGetUniformfvRobustANGLE(const Context *context,
433                                      ShaderProgramID program,
434                                      UniformLocation location,
435                                      GLsizei bufSize,
436                                      const GLsizei *length,
437                                      const GLfloat *params);
438 bool ValidateGetUniformivRobustANGLE(const Context *context,
439                                      ShaderProgramID program,
440                                      UniformLocation location,
441                                      GLsizei bufSize,
442                                      const GLsizei *length,
443                                      const GLint *params);
444 bool ValidateGetUniformuivRobustANGLE(const Context *context,
445                                       ShaderProgramID program,
446                                       UniformLocation location,
447                                       GLsizei bufSize,
448                                       const GLsizei *length,
449                                       const GLuint *params);
450 
451 bool ValidateDiscardFramebufferBase(const Context *context,
452                                     GLenum target,
453                                     GLsizei numAttachments,
454                                     const GLenum *attachments,
455                                     bool defaultFramebuffer);
456 
457 bool ValidateInsertEventMarkerEXT(const Context *context, GLsizei length, const char *marker);
458 bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker);
459 
460 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
461                                         TextureType type,
462                                         GLeglImageOES image);
463 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
464                                                   GLenum target,
465                                                   GLeglImageOES image);
466 
467 bool ValidateBindVertexArrayBase(const Context *context, VertexArrayID array);
468 
469 bool ValidateProgramBinaryBase(const Context *context,
470                                ShaderProgramID program,
471                                GLenum binaryFormat,
472                                const void *binary,
473                                GLint length);
474 bool ValidateGetProgramBinaryBase(const Context *context,
475                                   ShaderProgramID program,
476                                   GLsizei bufSize,
477                                   const GLsizei *length,
478                                   const GLenum *binaryFormat,
479                                   const void *binary);
480 
481 bool ValidateDrawBuffersBase(const Context *context, GLsizei n, const GLenum *bufs);
482 
483 bool ValidateGetBufferPointervBase(const Context *context,
484                                    BufferBinding target,
485                                    GLenum pname,
486                                    GLsizei *length,
487                                    void *const *params);
488 bool ValidateUnmapBufferBase(const Context *context, BufferBinding target);
489 bool ValidateMapBufferRangeBase(const Context *context,
490                                 BufferBinding target,
491                                 GLintptr offset,
492                                 GLsizeiptr length,
493                                 GLbitfield access);
494 bool ValidateFlushMappedBufferRangeBase(const Context *context,
495                                         BufferBinding target,
496                                         GLintptr offset,
497                                         GLsizeiptr length);
498 
499 bool ValidateGenOrDelete(const Context *context, GLint n);
500 
501 bool ValidateRobustEntryPoint(const Context *context, GLsizei bufSize);
502 bool ValidateRobustBufferSize(const Context *context, GLsizei bufSize, GLsizei numParams);
503 
504 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
505                                                      GLenum target,
506                                                      GLenum attachment,
507                                                      GLenum pname,
508                                                      GLsizei *numParams);
509 
510 bool ValidateGetBufferParameterBase(const Context *context,
511                                     BufferBinding target,
512                                     GLenum pname,
513                                     bool pointerVersion,
514                                     GLsizei *numParams);
515 
516 bool ValidateGetProgramivBase(const Context *context,
517                               ShaderProgramID program,
518                               GLenum pname,
519                               GLsizei *numParams);
520 
521 bool ValidateGetRenderbufferParameterivBase(const Context *context,
522                                             GLenum target,
523                                             GLenum pname,
524                                             GLsizei *length);
525 
526 bool ValidateGetShaderivBase(const Context *context,
527                              ShaderProgramID shader,
528                              GLenum pname,
529                              GLsizei *length);
530 
531 bool ValidateGetTexParameterBase(const Context *context,
532                                  TextureType target,
533                                  GLenum pname,
534                                  GLsizei *length);
535 
536 template <typename ParamType>
537 bool ValidateTexParameterBase(const Context *context,
538                               TextureType target,
539                               GLenum pname,
540                               GLsizei bufSize,
541                               bool vectorParams,
542                               const ParamType *params);
543 
544 bool ValidateGetVertexAttribBase(const Context *context,
545                                  GLuint index,
546                                  GLenum pname,
547                                  GLsizei *length,
548                                  bool pointer,
549                                  bool pureIntegerEntryPoint);
550 
ValidateVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribTypeCase validation)551 ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
552                                        GLuint index,
553                                        GLint size,
554                                        VertexAttribTypeCase validation)
555 {
556     const Caps &caps = context->getCaps();
557     if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
558     {
559         context->validationError(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
560         return false;
561     }
562 
563     switch (validation)
564     {
565         case VertexAttribTypeCase::Invalid:
566             context->validationError(GL_INVALID_ENUM, err::kInvalidType);
567             return false;
568         case VertexAttribTypeCase::Valid:
569             if (size < 1 || size > 4)
570             {
571                 context->validationError(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
572                 return false;
573             }
574             break;
575         case VertexAttribTypeCase::ValidSize4Only:
576             if (size != 4)
577             {
578                 context->validationError(GL_INVALID_OPERATION,
579                                          err::kInvalidVertexAttribSize2101010);
580                 return false;
581             }
582             break;
583         case VertexAttribTypeCase::ValidSize3or4:
584             if (size != 3 && size != 4)
585             {
586                 context->validationError(GL_INVALID_OPERATION,
587                                          err::kInvalidVertexAttribSize1010102);
588                 return false;
589             }
590             break;
591     }
592 
593     return true;
594 }
595 
596 // 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)597 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
598                                             GLuint index,
599                                             GLint size,
600                                             VertexAttribType type)
601 {
602     return ValidateVertexFormat(context, index, size,
603                                 context->getStateCache().getVertexAttribTypeValidation(type));
604 }
605 
ValidateIntegerVertexFormat(const Context * context,GLuint index,GLint size,VertexAttribType type)606 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
607                                               GLuint index,
608                                               GLint size,
609                                               VertexAttribType type)
610 {
611     return ValidateVertexFormat(
612         context, index, size, context->getStateCache().getIntegerVertexAttribTypeValidation(type));
613 }
614 
615 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
616                                                  GLint drawbuffer,
617                                                  const GLenum *validComponentTypes,
618                                                  size_t validComponentTypeCount);
619 
620 bool ValidateRobustCompressedTexImageBase(const Context *context,
621                                           GLsizei imageSize,
622                                           GLsizei dataSize);
623 
624 bool ValidateVertexAttribIndex(const Context *context, GLuint index);
625 
626 bool ValidateGetActiveUniformBlockivBase(const Context *context,
627                                          ShaderProgramID program,
628                                          GLuint uniformBlockIndex,
629                                          GLenum pname,
630                                          GLsizei *length);
631 
632 bool ValidateGetSamplerParameterBase(const Context *context,
633                                      SamplerID sampler,
634                                      GLenum pname,
635                                      GLsizei *length);
636 
637 template <typename ParamType>
638 bool ValidateSamplerParameterBase(const Context *context,
639                                   SamplerID sampler,
640                                   GLenum pname,
641                                   GLsizei bufSize,
642                                   bool vectorParams,
643                                   const ParamType *params);
644 
645 bool ValidateGetInternalFormativBase(const Context *context,
646                                      GLenum target,
647                                      GLenum internalformat,
648                                      GLenum pname,
649                                      GLsizei bufSize,
650                                      GLsizei *numParams);
651 
652 bool ValidateFramebufferNotMultisampled(const Context *context,
653                                         const Framebuffer *framebuffer,
654                                         bool needResourceSamples);
655 
656 bool ValidateMultitextureUnit(const Context *context, GLenum texture);
657 
658 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
659                                             PrimitiveMode transformFeedbackPrimitiveMode,
660                                             PrimitiveMode renderPrimitiveMode);
661 
662 // Common validation for 2D and 3D variants of TexStorage*Multisample.
663 bool ValidateTexStorageMultisample(const Context *context,
664                                    TextureType target,
665                                    GLsizei samples,
666                                    GLint internalFormat,
667                                    GLsizei width,
668                                    GLsizei height);
669 
670 bool ValidateTexStorage2DMultisampleBase(const Context *context,
671                                          TextureType target,
672                                          GLsizei samples,
673                                          GLint internalFormat,
674                                          GLsizei width,
675                                          GLsizei height);
676 
677 bool ValidateGetTexLevelParameterBase(const Context *context,
678                                       TextureTarget target,
679                                       GLint level,
680                                       GLenum pname,
681                                       GLsizei *length);
682 
683 bool ValidateMapBufferBase(const Context *context, BufferBinding target);
684 bool ValidateIndexedStateQuery(const Context *context, GLenum pname, GLuint index, GLsizei *length);
685 bool ValidateES3TexImage2DParameters(const Context *context,
686                                      TextureTarget target,
687                                      GLint level,
688                                      GLenum internalformat,
689                                      bool isCompressed,
690                                      bool isSubImage,
691                                      GLint xoffset,
692                                      GLint yoffset,
693                                      GLint zoffset,
694                                      GLsizei width,
695                                      GLsizei height,
696                                      GLsizei depth,
697                                      GLint border,
698                                      GLenum format,
699                                      GLenum type,
700                                      GLsizei imageSize,
701                                      const void *pixels);
702 bool ValidateES3CopyTexImage2DParameters(const Context *context,
703                                          TextureTarget target,
704                                          GLint level,
705                                          GLenum internalformat,
706                                          bool isSubImage,
707                                          GLint xoffset,
708                                          GLint yoffset,
709                                          GLint zoffset,
710                                          GLint x,
711                                          GLint y,
712                                          GLsizei width,
713                                          GLsizei height,
714                                          GLint border);
715 bool ValidateES3TexStorage2DParameters(const Context *context,
716                                        TextureType target,
717                                        GLsizei levels,
718                                        GLenum internalformat,
719                                        GLsizei width,
720                                        GLsizei height,
721                                        GLsizei depth);
722 bool ValidateES3TexStorage3DParameters(const Context *context,
723                                        TextureType target,
724                                        GLsizei levels,
725                                        GLenum internalformat,
726                                        GLsizei width,
727                                        GLsizei height,
728                                        GLsizei depth);
729 
730 bool ValidateGetMultisamplefvBase(const Context *context,
731                                   GLenum pname,
732                                   GLuint index,
733                                   const GLfloat *val);
734 bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask);
735 
736 // Utility macro for handling implementation methods inside Validation.
737 #define ANGLE_HANDLE_VALIDATION_ERR(X) \
738     (void)(X);                         \
739     return false
740 #define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR)
741 
742 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
743 // implementation format info for incomplete framebuffers. It seems like these queries are
744 // incongruent with the other errors.
745 // Inlined for speed.
746 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ValidateFramebufferComplete(const Context * context,const Framebuffer * framebuffer)747 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
748                                               const Framebuffer *framebuffer)
749 {
750     if (!framebuffer->isComplete(context))
751     {
752         context->validationError(ErrorCode, err::kFramebufferIncomplete);
753         return false;
754     }
755 
756     return true;
757 }
758 
759 const char *ValidateProgramDrawStates(const State &state,
760                                       const Extensions &extensions,
761                                       Program *program);
762 const char *ValidateProgramPipelineDrawStates(const State &state,
763                                               const Extensions &extensions,
764                                               ProgramPipeline *programPipeline);
765 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
766 const char *ValidateDrawStates(const Context *context);
767 
768 void RecordDrawAttribsError(const Context *context);
769 
ValidateDrawAttribs(const Context * context,int64_t maxVertex)770 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context, int64_t maxVertex)
771 {
772     if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit())
773     {
774         RecordDrawAttribsError(context);
775         return false;
776     }
777 
778     return true;
779 }
780 
ValidateDrawArraysAttribs(const Context * context,GLint first,GLsizei count)781 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context, GLint first, GLsizei count)
782 {
783     if (!context->isBufferAccessValidationEnabled())
784     {
785         return true;
786     }
787 
788     // Check the computation of maxVertex doesn't overflow.
789     // - first < 0 has been checked as an error condition.
790     // - if count <= 0, skip validating no-op draw calls.
791     // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
792     ASSERT(first >= 0);
793     ASSERT(count > 0);
794     int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
795     if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
796     {
797         context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
798         return false;
799     }
800 
801     return ValidateDrawAttribs(context, maxVertex);
802 }
803 
ValidateDrawInstancedAttribs(const Context * context,GLint primcount)804 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, GLint primcount)
805 {
806     if (!context->isBufferAccessValidationEnabled())
807     {
808         return true;
809     }
810 
811     if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit())
812     {
813         RecordDrawAttribsError(context);
814         return false;
815     }
816 
817     return true;
818 }
819 
ValidateDrawArraysCommon(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)820 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
821                                            PrimitiveMode mode,
822                                            GLint first,
823                                            GLsizei count,
824                                            GLsizei primcount)
825 {
826     if (first < 0)
827     {
828         context->validationError(GL_INVALID_VALUE, err::kNegativeStart);
829         return false;
830     }
831 
832     if (count <= 0)
833     {
834         if (count < 0)
835         {
836             context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
837             return false;
838         }
839 
840         // Early exit.
841         return ValidateDrawBase(context, mode);
842     }
843 
844     if (!ValidateDrawBase(context, mode))
845     {
846         return false;
847     }
848 
849     if (context->getStateCache().isTransformFeedbackActiveUnpaused())
850     {
851         const State &state                      = context->getState();
852         TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
853         if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
854         {
855             context->validationError(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
856             return false;
857         }
858     }
859 
860     return ValidateDrawArraysAttribs(context, first, count);
861 }
862 
ValidateDrawElementsBase(const Context * context,PrimitiveMode mode,DrawElementsType type)863 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
864                                            PrimitiveMode mode,
865                                            DrawElementsType type)
866 {
867     if (!context->getStateCache().isValidDrawElementsType(type))
868     {
869         if (type == DrawElementsType::UnsignedInt)
870         {
871             context->validationError(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
872             return false;
873         }
874 
875         ASSERT(type == DrawElementsType::InvalidEnum);
876         context->validationError(GL_INVALID_ENUM, err::kEnumNotSupported);
877         return false;
878     }
879 
880     intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
881     if (drawElementsError)
882     {
883         // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
884         const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
885         context->validationError(GL_INVALID_OPERATION, errorMessage);
886         return false;
887     }
888 
889     // Note that we are missing overflow checks for active transform feedback buffers.
890     return true;
891 }
892 
ValidateDrawElementsCommon(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)893 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
894                                              PrimitiveMode mode,
895                                              GLsizei count,
896                                              DrawElementsType type,
897                                              const void *indices,
898                                              GLsizei primcount)
899 {
900     if (!ValidateDrawElementsBase(context, mode, type))
901     {
902         return false;
903     }
904 
905     ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
906 
907     if (context->getExtensions().webglCompatibility)
908     {
909         GLuint typeBytes = GetDrawElementsTypeSize(type);
910 
911         if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
912         {
913             // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
914             // The offset arguments to drawElements and [...], must be a multiple of the size of the
915             // data type passed to the call, or an INVALID_OPERATION error is generated.
916             context->validationError(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
917             return false;
918         }
919 
920         // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
921         // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
922         // error is generated.
923         if (reinterpret_cast<intptr_t>(indices) < 0)
924         {
925             context->validationError(GL_INVALID_VALUE, err::kNegativeOffset);
926             return false;
927         }
928     }
929 
930     if (count <= 0)
931     {
932         if (count < 0)
933         {
934             context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
935             return false;
936         }
937 
938         // Early exit.
939         return ValidateDrawBase(context, mode);
940     }
941 
942     if (!ValidateDrawBase(context, mode))
943     {
944         return false;
945     }
946 
947     const State &state         = context->getState();
948     const VertexArray *vao     = state.getVertexArray();
949     Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
950 
951     if (!elementArrayBuffer)
952     {
953         if (!indices)
954         {
955             // This is an application error that would normally result in a crash, but we catch
956             // it and return an error
957             context->validationError(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
958             return false;
959         }
960     }
961     else
962     {
963         // The max possible type size is 8 and count is on 32 bits so doing the multiplication
964         // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
965         static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
966         constexpr uint64_t kMaxTypeSize = 8;
967         constexpr uint64_t kIntMax      = std::numeric_limits<int>::max();
968         constexpr uint64_t kUint64Max   = std::numeric_limits<uint64_t>::max();
969         static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
970 
971         uint64_t elementCount = static_cast<uint64_t>(count);
972         ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
973 
974         // Doing the multiplication here is overflow-safe
975         uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
976 
977         // The offset can be any value, check for overflows
978         uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
979         uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
980         if (elementDataSizeWithOffset < elementDataSizeNoOffset)
981         {
982             context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
983             return false;
984         }
985 
986         if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
987         {
988             context->validationError(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
989             return false;
990         }
991     }
992 
993     if (context->isBufferAccessValidationEnabled() && primcount > 0)
994     {
995         // Use the parameter buffer to retrieve and cache the index range.
996         IndexRange indexRange{IndexRange::Undefined()};
997         ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
998 
999         // If we use an index greater than our maximum supported index range, return an error.
1000         // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
1001         // always return an error if possible here.
1002         if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
1003         {
1004             context->validationError(GL_INVALID_OPERATION, err::kExceedsMaxElement);
1005             return false;
1006         }
1007 
1008         if (!ValidateDrawAttribs(context, static_cast<GLint>(indexRange.end)))
1009         {
1010             return false;
1011         }
1012 
1013         // No op if there are no real indices in the index data (all are primitive restart).
1014         return (indexRange.vertexIndexCount > 0);
1015     }
1016 
1017     return true;
1018 }
1019 }  // namespace gl
1020 
1021 #endif  // LIBANGLE_VALIDATION_ES_H_
1022