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