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