1 //
2 // Copyright (c) 2013-2014 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 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8 
9 #include "libANGLE/validationES3.h"
10 
11 #include "anglebase/numerics/safe_conversions.h"
12 #include "common/mathutil.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/ErrorStrings.h"
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 #include "libANGLE/Renderbuffer.h"
19 #include "libANGLE/Texture.h"
20 #include "libANGLE/formatutils.h"
21 #include "libANGLE/validationES.h"
22 
23 using namespace angle;
24 
25 namespace gl
26 {
27 
28 namespace
29 {
ValidateFramebufferTextureMultiviewBaseANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLsizei numViews)30 bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31                                                   GLenum target,
32                                                   GLenum attachment,
33                                                   GLuint texture,
34                                                   GLint level,
35                                                   GLsizei numViews)
36 {
37     if (!context->getExtensions().multiview)
38     {
39         context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40         return false;
41     }
42 
43     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44     {
45         return false;
46     }
47 
48     if (texture != 0 && numViews < 1)
49     {
50         context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51         return false;
52     }
53 
54     const Extensions &extensions = context->getExtensions();
55     if (static_cast<GLuint>(numViews) > extensions.maxViews)
56     {
57         context->handleError(InvalidValue()
58                              << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59         return false;
60     }
61 
62     return true;
63 }
64 
ValidateFramebufferTextureMultiviewLevelAndFormat(Context * context,Texture * texture,GLint level)65 bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66                                                        Texture *texture,
67                                                        GLint level)
68 {
69     GLenum texTarget = texture->getTarget();
70     if (!ValidMipLevel(context, texTarget, level))
71     {
72         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73         return false;
74     }
75 
76     const auto &format = texture->getFormat(texTarget, level);
77     if (format.info->compressed)
78     {
79         ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80         return false;
81     }
82     return true;
83 }
84 
ValidateUniformES3(Context * context,GLenum uniformType,GLint location,GLint count)85 bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86 {
87     if (context->getClientMajorVersion() < 3)
88     {
89         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90         return false;
91     }
92 
93     return ValidateUniform(context, uniformType, location, count);
94 }
95 
ValidateUniformMatrixES3(Context * context,GLenum valueType,GLint location,GLsizei count,GLboolean transpose)96 bool ValidateUniformMatrixES3(Context *context,
97                               GLenum valueType,
98                               GLint location,
99                               GLsizei count,
100                               GLboolean transpose)
101 {
102     // Check for ES3 uniform entry points
103     if (context->getClientMajorVersion() < 3)
104     {
105         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106         return false;
107     }
108 
109     return ValidateUniformMatrix(context, valueType, location, count, transpose);
110 }
111 
ValidateGenOrDeleteES3(Context * context,GLint n)112 bool ValidateGenOrDeleteES3(Context *context, GLint n)
113 {
114     if (context->getClientMajorVersion() < 3)
115     {
116         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117         return false;
118     }
119     return ValidateGenOrDelete(context, n);
120 }
121 
ValidateGenOrDeleteCountES3(Context * context,GLint count)122 bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123 {
124     if (context->getClientMajorVersion() < 3)
125     {
126         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127         return false;
128     }
129     if (count < 0)
130     {
131         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132         return false;
133     }
134     return true;
135 }
136 
137 }  // anonymous namespace
138 
ValidateTexImageFormatCombination(gl::Context * context,GLenum target,GLenum internalFormat,GLenum format,GLenum type)139 static bool ValidateTexImageFormatCombination(gl::Context *context,
140                                               GLenum target,
141                                               GLenum internalFormat,
142                                               GLenum format,
143                                               GLenum type)
144 {
145 
146     // The type and format are valid if any supported internal format has that type and format
147     if (!ValidES3Format(format))
148     {
149         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
150         return false;
151     }
152 
153     if (!ValidES3Type(type))
154     {
155         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
156         return false;
157     }
158 
159     // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160     // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161     // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162     // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163     if (!ValidES3InternalFormat(internalFormat))
164     {
165         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
166         return false;
167     }
168 
169     // From the ES 3.0 spec section 3.8.3:
170     // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171     // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172     // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173     // INVALID_OPERATION error.
174     if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175     {
176         context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177                                                    "GL_DEPTH_STENCIL if target is "
178                                                    "GL_TEXTURE_3D");
179         return false;
180     }
181 
182     // Check if this is a valid format combination to load texture data
183     if (!ValidES3FormatCombination(format, type, internalFormat))
184     {
185         context->handleError(InvalidOperation()
186                              << "Invalid combination of format, type and internalFormat.");
187         return false;
188     }
189 
190     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192     {
193         context->handleError(InvalidOperation() << "Unsupported internal format.");
194         return false;
195     }
196 
197     return true;
198 }
199 
ValidateES3TexImageParametersBase(Context * context,GLenum target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)200 bool ValidateES3TexImageParametersBase(Context *context,
201                                        GLenum target,
202                                        GLint level,
203                                        GLenum internalformat,
204                                        bool isCompressed,
205                                        bool isSubImage,
206                                        GLint xoffset,
207                                        GLint yoffset,
208                                        GLint zoffset,
209                                        GLsizei width,
210                                        GLsizei height,
211                                        GLsizei depth,
212                                        GLint border,
213                                        GLenum format,
214                                        GLenum type,
215                                        GLsizei imageSize,
216                                        const void *pixels)
217 {
218     // Validate image size
219     if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
220     {
221         context->handleError(InvalidValue());
222         return false;
223     }
224 
225     // Verify zero border
226     if (border != 0)
227     {
228         context->handleError(InvalidValue());
229         return false;
230     }
231 
232     if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233         std::numeric_limits<GLsizei>::max() - xoffset < width ||
234         std::numeric_limits<GLsizei>::max() - yoffset < height ||
235         std::numeric_limits<GLsizei>::max() - zoffset < depth)
236     {
237         context->handleError(InvalidValue());
238         return false;
239     }
240 
241     const gl::Caps &caps = context->getCaps();
242 
243     switch (target)
244     {
245         case GL_TEXTURE_2D:
246             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248             {
249                 context->handleError(InvalidValue());
250                 return false;
251             }
252             break;
253 
254         case GL_TEXTURE_RECTANGLE_ANGLE:
255             ASSERT(level == 0);
256             if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257                 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258             {
259                 context->handleError(InvalidValue());
260                 return false;
261             }
262             if (isCompressed)
263             {
264                 context->handleError(InvalidEnum()
265                                      << "Rectangle texture cannot have a compressed format.");
266                 return false;
267             }
268             break;
269 
270         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276             if (!isSubImage && width != height)
277             {
278                 context->handleError(InvalidValue());
279                 return false;
280             }
281 
282             if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283             {
284                 context->handleError(InvalidValue());
285                 return false;
286             }
287             break;
288 
289         case GL_TEXTURE_3D:
290             if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291                 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292                 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293             {
294                 context->handleError(InvalidValue());
295                 return false;
296             }
297             break;
298 
299         case GL_TEXTURE_2D_ARRAY:
300             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302                 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303             {
304                 context->handleError(InvalidValue());
305                 return false;
306             }
307             break;
308 
309         default:
310             context->handleError(InvalidEnum());
311             return false;
312     }
313 
314     gl::Texture *texture =
315         context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
316     if (!texture)
317     {
318         context->handleError(InvalidOperation());
319         return false;
320     }
321 
322     if (texture->getImmutableFormat() && !isSubImage)
323     {
324         context->handleError(InvalidOperation());
325         return false;
326     }
327 
328     // Validate texture formats
329     GLenum actualInternalFormat =
330         isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
331     if (isSubImage && actualInternalFormat == GL_NONE)
332     {
333         context->handleError(InvalidOperation() << "Texture level does not exist.");
334         return false;
335     }
336 
337     const gl::InternalFormat &actualFormatInfo = isSubImage
338                                                      ? *texture->getFormat(target, level).info
339                                                      : GetInternalFormatInfo(internalformat, type);
340     if (isCompressed)
341     {
342         if (!actualFormatInfo.compressed)
343         {
344             context->handleError(
345                 InvalidEnum() << "internalformat is not a supported compressed internal format.");
346             return false;
347         }
348 
349         if (isSubImage)
350         {
351             if (!ValidCompressedSubImageSize(
352                     context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353                     texture->getWidth(target, level), texture->getHeight(target, level)))
354             {
355                 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
356                 return false;
357             }
358 
359             if (format != actualInternalFormat)
360             {
361                 context->handleError(InvalidOperation()
362                                      << "Format must match the internal format of the texture.");
363                 return false;
364             }
365 
366             if (actualInternalFormat == GL_ETC1_RGB8_OES)
367             {
368                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369                 return false;
370             }
371         }
372         else
373         {
374             if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375             {
376                 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
377                 return false;
378             }
379         }
380 
381         if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
382         {
383             context->handleError(InvalidEnum());
384             return false;
385         }
386 
387         if (target == GL_TEXTURE_3D)
388         {
389             context->handleError(InvalidOperation());
390             return false;
391         }
392     }
393     else
394     {
395         if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
396         {
397             return false;
398         }
399     }
400 
401     // Validate sub image parameters
402     if (isSubImage)
403     {
404         if (isCompressed != actualFormatInfo.compressed)
405         {
406             context->handleError(InvalidOperation());
407             return false;
408         }
409 
410         if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411         {
412             context->handleError(InvalidValue());
413             return false;
414         }
415 
416         if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417             std::numeric_limits<GLsizei>::max() - yoffset < height ||
418             std::numeric_limits<GLsizei>::max() - zoffset < depth)
419         {
420             context->handleError(InvalidValue());
421             return false;
422         }
423 
424         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426             static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
427         {
428             context->handleError(InvalidValue());
429             return false;
430         }
431 
432         if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
433             context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
434         {
435             ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
436             return false;
437         }
438     }
439 
440     GLenum sizeCheckFormat = isSubImage ? format : internalformat;
441     if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
442                             imageSize))
443     {
444         return false;
445     }
446 
447     // Check for pixel unpack buffer related API errors
448     gl::Buffer *pixelUnpackBuffer =
449         context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
450     if (pixelUnpackBuffer != nullptr)
451     {
452         // ...data is not evenly divisible into the number of bytes needed to store in memory a
453         // datum
454         // indicated by type.
455         if (!isCompressed)
456         {
457             size_t offset            = reinterpret_cast<size_t>(pixels);
458             size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
459 
460             if ((offset % dataBytesPerPixel) != 0)
461             {
462                 context->handleError(InvalidOperation()
463                                      << "Reads would overflow the pixel unpack buffer.");
464                 return false;
465             }
466         }
467 
468         // ...the buffer object's data store is currently mapped.
469         if (pixelUnpackBuffer->isMapped())
470         {
471             context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
472             return false;
473         }
474     }
475 
476     return true;
477 }
478 
ValidateES3TexImage2DParameters(Context * context,GLenum target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)479 bool ValidateES3TexImage2DParameters(Context *context,
480                                      GLenum target,
481                                      GLint level,
482                                      GLenum internalformat,
483                                      bool isCompressed,
484                                      bool isSubImage,
485                                      GLint xoffset,
486                                      GLint yoffset,
487                                      GLint zoffset,
488                                      GLsizei width,
489                                      GLsizei height,
490                                      GLsizei depth,
491                                      GLint border,
492                                      GLenum format,
493                                      GLenum type,
494                                      GLsizei imageSize,
495                                      const void *pixels)
496 {
497     if (!ValidTexture2DDestinationTarget(context, target))
498     {
499         context->handleError(InvalidEnum());
500         return false;
501     }
502 
503     return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
504                                              isSubImage, xoffset, yoffset, zoffset, width, height,
505                                              depth, border, format, type, imageSize, pixels);
506 }
507 
ValidateES3TexImage3DParameters(Context * context,GLenum target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)508 bool ValidateES3TexImage3DParameters(Context *context,
509                                      GLenum target,
510                                      GLint level,
511                                      GLenum internalformat,
512                                      bool isCompressed,
513                                      bool isSubImage,
514                                      GLint xoffset,
515                                      GLint yoffset,
516                                      GLint zoffset,
517                                      GLsizei width,
518                                      GLsizei height,
519                                      GLsizei depth,
520                                      GLint border,
521                                      GLenum format,
522                                      GLenum type,
523                                      GLsizei bufSize,
524                                      const void *pixels)
525 {
526     if (!ValidTexture3DDestinationTarget(context, target))
527     {
528         context->handleError(InvalidEnum());
529         return false;
530     }
531 
532     return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
533                                              isSubImage, xoffset, yoffset, zoffset, width, height,
534                                              depth, border, format, type, bufSize, pixels);
535 }
536 
537 struct EffectiveInternalFormatInfo
538 {
539     GLenum effectiveFormat;
540     GLenum destFormat;
541     GLuint minRedBits;
542     GLuint maxRedBits;
543     GLuint minGreenBits;
544     GLuint maxGreenBits;
545     GLuint minBlueBits;
546     GLuint maxBlueBits;
547     GLuint minAlphaBits;
548     GLuint maxAlphaBits;
549 };
550 
QueryEffectiveFormatList(const InternalFormat & srcFormat,GLenum targetFormat,const EffectiveInternalFormatInfo * list,size_t size,GLenum * outEffectiveFormat)551 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
552                                      GLenum targetFormat,
553                                      const EffectiveInternalFormatInfo *list,
554                                      size_t size,
555                                      GLenum *outEffectiveFormat)
556 {
557     for (size_t curFormat = 0; curFormat < size; ++curFormat)
558     {
559         const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
560         if ((formatInfo.destFormat == targetFormat) &&
561             (formatInfo.minRedBits <= srcFormat.redBits &&
562              formatInfo.maxRedBits >= srcFormat.redBits) &&
563             (formatInfo.minGreenBits <= srcFormat.greenBits &&
564              formatInfo.maxGreenBits >= srcFormat.greenBits) &&
565             (formatInfo.minBlueBits <= srcFormat.blueBits &&
566              formatInfo.maxBlueBits >= srcFormat.blueBits) &&
567             (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
568              formatInfo.maxAlphaBits >= srcFormat.alphaBits))
569         {
570             *outEffectiveFormat = formatInfo.effectiveFormat;
571             return true;
572         }
573     }
574 
575     *outEffectiveFormat = GL_NONE;
576     return false;
577 }
578 
GetSizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,GLenum * outEffectiveFormat)579 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
580                                          GLenum *outEffectiveFormat)
581 {
582     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
583     // Effective internal format coresponding to destination internal format and linear source
584     // buffer component sizes.
585     //                                       | Source channel min/max sizes |
586     //   Effective Internal Format   |  N/A  |  R   |  G   |  B   |  A      |
587     // clang-format off
588     constexpr EffectiveInternalFormatInfo list[] = {
589         { GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8 },
590         { GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0 },
591         { GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0 },
592         { GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0 },
593         { GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0 },
594         { GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4 },
595         { GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1 },
596         { GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8 },
597         { GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
598     };
599     // clang-format on
600 
601     return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
602 }
603 
GetUnsizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)604 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
605                                            const InternalFormat &destFormat,
606                                            GLenum *outEffectiveFormat)
607 {
608     constexpr GLuint umax = UINT_MAX;
609 
610     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
611     // Effective internal format coresponding to destination internal format andlinear source buffer
612     // component sizes.
613     //                                                   |   Source channel min/max sizes   |
614     //     Effective Internal Format |   Dest Format     |   R   |    G   |    B   |    A   |
615     // clang-format off
616     constexpr EffectiveInternalFormatInfo list[] = {
617         { GL_ALPHA8_EXT,             GL_ALPHA,           0, umax, 0, umax, 0, umax, 1,    8 },
618         { GL_LUMINANCE8_EXT,         GL_LUMINANCE,       1,    8, 0, umax, 0, umax, 0, umax },
619         { GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, 1,    8, 0, umax, 0, umax, 1,    8 },
620         { GL_RGB565,                 GL_RGB,             1,    5, 1,    6, 1,    5, 0, umax },
621         { GL_RGB8,                   GL_RGB,             6,    8, 7,    8, 6,    8, 0, umax },
622         { GL_RGBA4,                  GL_RGBA,            1,    4, 1,    4, 1,    4, 1,    4 },
623         { GL_RGB5_A1,                GL_RGBA,            5,    5, 5,    5, 5,    5, 1,    1 },
624         { GL_RGBA8,                  GL_RGBA,            5,    8, 5,    8, 5,    8, 5,    8 },
625     };
626     // clang-format on
627 
628     return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
629                                     outEffectiveFormat);
630 }
631 
GetEffectiveInternalFormat(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)632 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
633                                        const InternalFormat &destFormat,
634                                        GLenum *outEffectiveFormat)
635 {
636     if (destFormat.sized)
637     {
638         return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
639     }
640     else
641     {
642         return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
643     }
644 }
645 
EqualOrFirstZero(GLuint first,GLuint second)646 static bool EqualOrFirstZero(GLuint first, GLuint second)
647 {
648     return first == 0 || first == second;
649 }
650 
IsValidES3CopyTexImageCombination(const InternalFormat & textureFormatInfo,const InternalFormat & framebufferFormatInfo,GLuint readBufferHandle)651 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
652                                               const InternalFormat &framebufferFormatInfo,
653                                               GLuint readBufferHandle)
654 {
655     if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
656     {
657         return false;
658     }
659 
660     // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
661     // must both be signed, unsigned, or fixed point and both source and destinations
662     // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
663     // conversion between fixed and floating point.
664 
665     if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
666         (framebufferFormatInfo.colorEncoding == GL_SRGB))
667     {
668         return false;
669     }
670 
671     if (((textureFormatInfo.componentType == GL_INT) !=
672          (framebufferFormatInfo.componentType == GL_INT)) ||
673         ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
674          (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
675     {
676         return false;
677     }
678 
679     if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
680          textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
681          textureFormatInfo.componentType == GL_FLOAT) &&
682         !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
683           framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
684           framebufferFormatInfo.componentType == GL_FLOAT))
685     {
686         return false;
687     }
688 
689     // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
690     // The effective internal format of the source buffer is determined with the following rules
691     // applied in order:
692     //    * If the source buffer is a texture or renderbuffer that was created with a sized internal
693     //      format then the effective internal format is the source buffer's sized internal format.
694     //    * If the source buffer is a texture that was created with an unsized base internal format,
695     //      then the effective internal format is the source image array's effective internal
696     //      format, as specified by table 3.12, which is determined from the <format> and <type>
697     //      that were used when the source image array was specified by TexImage*.
698     //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
699     //      where Destination Internal Format matches internalformat and where the [source channel
700     //      sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
701     //      is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
702     //      FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
703     const InternalFormat *sourceEffectiveFormat = nullptr;
704     if (readBufferHandle != 0)
705     {
706         // Not the default framebuffer, therefore the read buffer must be a user-created texture or
707         // renderbuffer
708         if (framebufferFormatInfo.sized)
709         {
710             sourceEffectiveFormat = &framebufferFormatInfo;
711         }
712         else
713         {
714             // Renderbuffers cannot be created with an unsized internal format, so this must be an
715             // unsized-format texture. We can use the same table we use when creating textures to
716             // get its effective sized format.
717             sourceEffectiveFormat =
718                 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
719         }
720     }
721     else
722     {
723         // The effective internal format must be derived from the source framebuffer's channel
724         // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
725         if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
726         {
727             GLenum effectiveFormat;
728             if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
729                                            &effectiveFormat))
730             {
731                 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
732             }
733             else
734             {
735                 return false;
736             }
737         }
738         else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
739         {
740             // SRGB buffers can only be copied to sized format destinations according to table 3.18
741             if (textureFormatInfo.sized &&
742                 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
743                 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
744                 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
745                 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
746             {
747                 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
748             }
749             else
750             {
751                 return false;
752             }
753         }
754         else
755         {
756             UNREACHABLE();
757             return false;
758         }
759     }
760 
761     if (textureFormatInfo.sized)
762     {
763         // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
764         // sized, component sizes of the source and destination formats must exactly match if the
765         // destination format exists.
766         if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
767             !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
768             !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
769             !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
770         {
771             return false;
772         }
773     }
774 
775     return true;  // A conversion function exists, and no rule in the specification has precluded
776                   // conversion between these formats.
777 }
778 
ValidateES3CopyTexImageParametersBase(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)779 bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
780                                            GLenum target,
781                                            GLint level,
782                                            GLenum internalformat,
783                                            bool isSubImage,
784                                            GLint xoffset,
785                                            GLint yoffset,
786                                            GLint zoffset,
787                                            GLint x,
788                                            GLint y,
789                                            GLsizei width,
790                                            GLsizei height,
791                                            GLint border)
792 {
793     Format textureFormat = Format::Invalid();
794     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
795                                             xoffset, yoffset, zoffset, x, y, width, height, border,
796                                             &textureFormat))
797     {
798         return false;
799     }
800     ASSERT(textureFormat.valid() || !isSubImage);
801 
802     const auto &state            = context->getGLState();
803     gl::Framebuffer *framebuffer = state.getReadFramebuffer();
804     GLuint readFramebufferID     = framebuffer->id();
805 
806     if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
807     {
808         context->handleError(InvalidFramebufferOperation());
809         return false;
810     }
811 
812     if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
813     {
814         context->handleError(InvalidOperation());
815         return false;
816     }
817 
818     const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
819 
820     if (isSubImage)
821     {
822         if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
823                                                readFramebufferID))
824         {
825             context->handleError(InvalidOperation());
826             return false;
827         }
828     }
829     else
830     {
831         // Use format/type from the source FBO. (Might not be perfect for all cases?)
832         const InternalFormat &framebufferFormat = *source->getFormat().info;
833         const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
834         if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
835         {
836             context->handleError(InvalidOperation());
837             return false;
838         }
839     }
840 
841     // If width or height is zero, it is a no-op.  Return false without setting an error.
842     return (width > 0 && height > 0);
843 }
844 
ValidateES3CopyTexImage2DParameters(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)845 bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
846                                          GLenum target,
847                                          GLint level,
848                                          GLenum internalformat,
849                                          bool isSubImage,
850                                          GLint xoffset,
851                                          GLint yoffset,
852                                          GLint zoffset,
853                                          GLint x,
854                                          GLint y,
855                                          GLsizei width,
856                                          GLsizei height,
857                                          GLint border)
858 {
859     if (!ValidTexture2DDestinationTarget(context, target))
860     {
861         context->handleError(InvalidEnum());
862         return false;
863     }
864 
865     return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
866                                                  xoffset, yoffset, zoffset, x, y, width, height,
867                                                  border);
868 }
869 
ValidateES3CopyTexImage3DParameters(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)870 bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
871                                          GLenum target,
872                                          GLint level,
873                                          GLenum internalformat,
874                                          bool isSubImage,
875                                          GLint xoffset,
876                                          GLint yoffset,
877                                          GLint zoffset,
878                                          GLint x,
879                                          GLint y,
880                                          GLsizei width,
881                                          GLsizei height,
882                                          GLint border)
883 {
884     if (!ValidTexture3DDestinationTarget(context, target))
885     {
886         context->handleError(InvalidEnum());
887         return false;
888     }
889 
890     return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
891                                                  xoffset, yoffset, zoffset, x, y, width, height,
892                                                  border);
893 }
894 
ValidateES3TexStorageParametersBase(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)895 bool ValidateES3TexStorageParametersBase(Context *context,
896                                          GLenum target,
897                                          GLsizei levels,
898                                          GLenum internalformat,
899                                          GLsizei width,
900                                          GLsizei height,
901                                          GLsizei depth)
902 {
903     if (width < 1 || height < 1 || depth < 1 || levels < 1)
904     {
905         context->handleError(InvalidValue());
906         return false;
907     }
908 
909     GLsizei maxDim = std::max(width, height);
910     if (target != GL_TEXTURE_2D_ARRAY)
911     {
912         maxDim = std::max(maxDim, depth);
913     }
914 
915     if (levels > gl::log2(maxDim) + 1)
916     {
917         context->handleError(InvalidOperation());
918         return false;
919     }
920 
921     const gl::Caps &caps = context->getCaps();
922 
923     switch (target)
924     {
925         case GL_TEXTURE_2D:
926         {
927             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
928                 static_cast<GLuint>(height) > caps.max2DTextureSize)
929             {
930                 context->handleError(InvalidValue());
931                 return false;
932             }
933         }
934         break;
935 
936         case GL_TEXTURE_RECTANGLE_ANGLE:
937         {
938             if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
939                 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
940             {
941                 context->handleError(InvalidValue());
942                 return false;
943             }
944         }
945         break;
946 
947         case GL_TEXTURE_CUBE_MAP:
948         {
949             if (width != height)
950             {
951                 context->handleError(InvalidValue());
952                 return false;
953             }
954 
955             if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
956             {
957                 context->handleError(InvalidValue());
958                 return false;
959             }
960         }
961         break;
962 
963         case GL_TEXTURE_3D:
964         {
965             if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
966                 static_cast<GLuint>(height) > caps.max3DTextureSize ||
967                 static_cast<GLuint>(depth) > caps.max3DTextureSize)
968             {
969                 context->handleError(InvalidValue());
970                 return false;
971             }
972         }
973         break;
974 
975         case GL_TEXTURE_2D_ARRAY:
976         {
977             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
978                 static_cast<GLuint>(height) > caps.max2DTextureSize ||
979                 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
980             {
981                 context->handleError(InvalidValue());
982                 return false;
983             }
984         }
985         break;
986 
987         default:
988             UNREACHABLE();
989             return false;
990     }
991 
992     gl::Texture *texture = context->getTargetTexture(target);
993     if (!texture || texture->id() == 0)
994     {
995         context->handleError(InvalidOperation());
996         return false;
997     }
998 
999     if (texture->getImmutableFormat())
1000     {
1001         context->handleError(InvalidOperation());
1002         return false;
1003     }
1004 
1005     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
1006     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1007     {
1008         context->handleError(InvalidEnum());
1009         return false;
1010     }
1011 
1012     if (!formatInfo.sized)
1013     {
1014         context->handleError(InvalidEnum());
1015         return false;
1016     }
1017 
1018     if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1019     {
1020         context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1021         return false;
1022     }
1023 
1024     return true;
1025 }
1026 
ValidateES3TexStorage2DParameters(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1027 bool ValidateES3TexStorage2DParameters(Context *context,
1028                                        GLenum target,
1029                                        GLsizei levels,
1030                                        GLenum internalformat,
1031                                        GLsizei width,
1032                                        GLsizei height,
1033                                        GLsizei depth)
1034 {
1035     if (!ValidTexture2DTarget(context, target))
1036     {
1037         context->handleError(InvalidEnum());
1038         return false;
1039     }
1040 
1041     return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1042                                                height, depth);
1043 }
1044 
ValidateES3TexStorage3DParameters(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1045 bool ValidateES3TexStorage3DParameters(Context *context,
1046                                        GLenum target,
1047                                        GLsizei levels,
1048                                        GLenum internalformat,
1049                                        GLsizei width,
1050                                        GLsizei height,
1051                                        GLsizei depth)
1052 {
1053     if (!ValidTexture3DTarget(context, target))
1054     {
1055         context->handleError(InvalidEnum());
1056         return false;
1057     }
1058 
1059     return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1060                                                height, depth);
1061 }
1062 
ValidateBeginQuery(gl::Context * context,GLenum target,GLuint id)1063 bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1064 {
1065     if (context->getClientMajorVersion() < 3)
1066     {
1067         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1068         return false;
1069     }
1070 
1071     return ValidateBeginQueryBase(context, target, id);
1072 }
1073 
ValidateEndQuery(gl::Context * context,GLenum target)1074 bool ValidateEndQuery(gl::Context *context, GLenum target)
1075 {
1076     if (context->getClientMajorVersion() < 3)
1077     {
1078         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1079         return false;
1080     }
1081 
1082     return ValidateEndQueryBase(context, target);
1083 }
1084 
ValidateGetQueryiv(Context * context,GLenum target,GLenum pname,GLint * params)1085 bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1086 {
1087     if (context->getClientMajorVersion() < 3)
1088     {
1089         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1090         return false;
1091     }
1092 
1093     return ValidateGetQueryivBase(context, target, pname, nullptr);
1094 }
1095 
ValidateGetQueryObjectuiv(Context * context,GLuint id,GLenum pname,GLuint * params)1096 bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1097 {
1098     if (context->getClientMajorVersion() < 3)
1099     {
1100         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1101         return false;
1102     }
1103 
1104     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1105 }
1106 
ValidateFramebufferTextureLayer(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)1107 bool ValidateFramebufferTextureLayer(Context *context,
1108                                      GLenum target,
1109                                      GLenum attachment,
1110                                      GLuint texture,
1111                                      GLint level,
1112                                      GLint layer)
1113 {
1114     if (context->getClientMajorVersion() < 3)
1115     {
1116         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1117         return false;
1118     }
1119 
1120     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1121     {
1122         return false;
1123     }
1124 
1125     const gl::Caps &caps = context->getCaps();
1126     if (texture != 0)
1127     {
1128         if (layer < 0)
1129         {
1130             context->handleError(InvalidValue());
1131             return false;
1132         }
1133 
1134         gl::Texture *tex = context->getTexture(texture);
1135         ASSERT(tex);
1136 
1137         switch (tex->getTarget())
1138         {
1139             case GL_TEXTURE_2D_ARRAY:
1140             {
1141                 if (level > gl::log2(caps.max2DTextureSize))
1142                 {
1143                     context->handleError(InvalidValue());
1144                     return false;
1145                 }
1146 
1147                 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1148                 {
1149                     context->handleError(InvalidValue());
1150                     return false;
1151                 }
1152             }
1153             break;
1154 
1155             case GL_TEXTURE_3D:
1156             {
1157                 if (level > gl::log2(caps.max3DTextureSize))
1158                 {
1159                     context->handleError(InvalidValue());
1160                     return false;
1161                 }
1162 
1163                 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1164                 {
1165                     context->handleError(InvalidValue());
1166                     return false;
1167                 }
1168             }
1169             break;
1170 
1171             default:
1172                 context->handleError(InvalidOperation());
1173                 return false;
1174         }
1175 
1176         const auto &format = tex->getFormat(tex->getTarget(), level);
1177         if (format.info->compressed)
1178         {
1179             context->handleError(InvalidOperation());
1180             return false;
1181         }
1182     }
1183 
1184     return true;
1185 }
1186 
ValidateInvalidateFramebuffer(Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)1187 bool ValidateInvalidateFramebuffer(Context *context,
1188                                    GLenum target,
1189                                    GLsizei numAttachments,
1190                                    const GLenum *attachments)
1191 {
1192     if (context->getClientMajorVersion() < 3)
1193     {
1194         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1195         return false;
1196     }
1197 
1198     bool defaultFramebuffer = false;
1199 
1200     switch (target)
1201     {
1202         case GL_DRAW_FRAMEBUFFER:
1203         case GL_FRAMEBUFFER:
1204             defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1205             break;
1206         case GL_READ_FRAMEBUFFER:
1207             defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1208             break;
1209         default:
1210             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
1211             return false;
1212     }
1213 
1214     return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1215                                           defaultFramebuffer);
1216 }
1217 
ValidateInvalidateSubFramebuffer(Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)1218 bool ValidateInvalidateSubFramebuffer(Context *context,
1219                                       GLenum target,
1220                                       GLsizei numAttachments,
1221                                       const GLenum *attachments,
1222                                       GLint x,
1223                                       GLint y,
1224                                       GLsizei width,
1225                                       GLsizei height)
1226 {
1227     return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1228 }
1229 
ValidateClearBuffer(ValidationContext * context)1230 bool ValidateClearBuffer(ValidationContext *context)
1231 {
1232     if (context->getClientMajorVersion() < 3)
1233     {
1234         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1235         return false;
1236     }
1237 
1238     if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
1239     {
1240         context->handleError(InvalidFramebufferOperation());
1241         return false;
1242     }
1243 
1244     return true;
1245 }
1246 
ValidateDrawRangeElements(Context * context,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const void * indices)1247 bool ValidateDrawRangeElements(Context *context,
1248                                GLenum mode,
1249                                GLuint start,
1250                                GLuint end,
1251                                GLsizei count,
1252                                GLenum type,
1253                                const void *indices)
1254 {
1255     if (context->getClientMajorVersion() < 3)
1256     {
1257         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1258         return false;
1259     }
1260 
1261     if (end < start)
1262     {
1263         context->handleError(InvalidValue() << "end < start");
1264         return false;
1265     }
1266 
1267     if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
1268     {
1269         return false;
1270     }
1271 
1272     // Use the parameter buffer to retrieve and cache the index range.
1273     const auto &params        = context->getParams<HasIndexRange>();
1274     const auto &indexRangeOpt = params.getIndexRange();
1275     if (!indexRangeOpt.valid())
1276     {
1277         // Unexpected error.
1278         return false;
1279     }
1280 
1281     if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
1282     {
1283         // GL spec says that behavior in this case is undefined - generating an error is fine.
1284         context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
1285         return false;
1286     }
1287     return true;
1288 }
1289 
ValidateGetUniformuiv(Context * context,GLuint program,GLint location,GLuint * params)1290 bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
1291 {
1292     if (context->getClientMajorVersion() < 3)
1293     {
1294         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1295         return false;
1296     }
1297 
1298     return ValidateGetUniformBase(context, program, location);
1299 }
1300 
ValidateReadBuffer(Context * context,GLenum src)1301 bool ValidateReadBuffer(Context *context, GLenum src)
1302 {
1303     if (context->getClientMajorVersion() < 3)
1304     {
1305         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1306         return false;
1307     }
1308 
1309     const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
1310 
1311     if (readFBO == nullptr)
1312     {
1313         context->handleError(InvalidOperation() << "No active read framebuffer.");
1314         return false;
1315     }
1316 
1317     if (src == GL_NONE)
1318     {
1319         return true;
1320     }
1321 
1322     if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
1323     {
1324         context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
1325         return false;
1326     }
1327 
1328     if (readFBO->id() == 0)
1329     {
1330         if (src != GL_BACK)
1331         {
1332             context->handleError(
1333                 InvalidOperation()
1334                 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
1335             return false;
1336         }
1337     }
1338     else
1339     {
1340         GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1341 
1342         if (drawBuffer >= context->getCaps().maxDrawBuffers)
1343         {
1344             context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
1345             return false;
1346         }
1347     }
1348 
1349     return true;
1350 }
1351 
ValidateCompressedTexImage3D(Context * context,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)1352 bool ValidateCompressedTexImage3D(Context *context,
1353                                   GLenum target,
1354                                   GLint level,
1355                                   GLenum internalformat,
1356                                   GLsizei width,
1357                                   GLsizei height,
1358                                   GLsizei depth,
1359                                   GLint border,
1360                                   GLsizei imageSize,
1361                                   const void *data)
1362 {
1363     if (context->getClientMajorVersion() < 3)
1364     {
1365         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1366         return false;
1367     }
1368 
1369     if (!ValidTextureTarget(context, target))
1370     {
1371         context->handleError(InvalidEnum());
1372         return false;
1373     }
1374 
1375     // Validate image size
1376     if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1377     {
1378         context->handleError(InvalidValue());
1379         return false;
1380     }
1381 
1382     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1383     if (!formatInfo.compressed)
1384     {
1385         context->handleError(InvalidEnum() << "Not a valid compressed texture format");
1386         return false;
1387     }
1388 
1389     auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
1390     if (blockSizeOrErr.isError())
1391     {
1392         context->handleError(InvalidValue());
1393         return false;
1394     }
1395     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
1396     {
1397         context->handleError(InvalidValue());
1398         return false;
1399     }
1400 
1401     // 3D texture target validation
1402     if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1403     {
1404         context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
1405         return false;
1406     }
1407 
1408     // validateES3TexImageFormat sets the error code if there is an error
1409     if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1410                                          0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1411                                          data))
1412     {
1413         return false;
1414     }
1415 
1416     return true;
1417 }
1418 
ValidateCompressedTexImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)1419 bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1420                                              GLenum target,
1421                                              GLint level,
1422                                              GLenum internalformat,
1423                                              GLsizei width,
1424                                              GLsizei height,
1425                                              GLsizei depth,
1426                                              GLint border,
1427                                              GLsizei imageSize,
1428                                              GLsizei dataSize,
1429                                              const void *data)
1430 {
1431     if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1432     {
1433         return false;
1434     }
1435 
1436     return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1437                                         depth, border, imageSize, data);
1438 }
1439 
ValidateBindVertexArray(Context * context,GLuint array)1440 bool ValidateBindVertexArray(Context *context, GLuint array)
1441 {
1442     if (context->getClientMajorVersion() < 3)
1443     {
1444         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1445         return false;
1446     }
1447 
1448     return ValidateBindVertexArrayBase(context, array);
1449 }
1450 
ValidateIsVertexArray(Context * context,GLuint array)1451 bool ValidateIsVertexArray(Context *context, GLuint array)
1452 {
1453     if (context->getClientMajorVersion() < 3)
1454     {
1455         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1456         return false;
1457     }
1458 
1459     return true;
1460 }
1461 
ValidateBindBufferCommon(Context * context,BufferBinding target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)1462 static bool ValidateBindBufferCommon(Context *context,
1463                                      BufferBinding target,
1464                                      GLuint index,
1465                                      GLuint buffer,
1466                                      GLintptr offset,
1467                                      GLsizeiptr size)
1468 {
1469     if (context->getClientMajorVersion() < 3)
1470     {
1471         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1472         return false;
1473     }
1474 
1475     if (buffer != 0 && offset < 0)
1476     {
1477         context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
1478         return false;
1479     }
1480 
1481     if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1482         !context->isBufferGenerated(buffer))
1483     {
1484         context->handleError(InvalidOperation() << "Buffer was not generated.");
1485         return false;
1486     }
1487 
1488     const Caps &caps = context->getCaps();
1489     switch (target)
1490     {
1491         case BufferBinding::TransformFeedback:
1492         {
1493             if (index >= caps.maxTransformFeedbackSeparateAttributes)
1494             {
1495                 context->handleError(InvalidValue() << "index is greater than or equal to the "
1496                                                        "number of TRANSFORM_FEEDBACK_BUFFER "
1497                                                        "indexed binding points.");
1498                 return false;
1499             }
1500             if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1501             {
1502                 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
1503                 return false;
1504             }
1505 
1506             TransformFeedback *curTransformFeedback =
1507                 context->getGLState().getCurrentTransformFeedback();
1508             if (curTransformFeedback && curTransformFeedback->isActive())
1509             {
1510                 context->handleError(InvalidOperation()
1511                                      << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1512                                         "feedback is currently active.");
1513                 return false;
1514             }
1515             break;
1516         }
1517         case BufferBinding::Uniform:
1518         {
1519             if (index >= caps.maxUniformBufferBindings)
1520             {
1521                 context->handleError(InvalidValue() << "index is greater than or equal to the "
1522                                                        "number of UNIFORM_BUFFER indexed "
1523                                                        "binding points.");
1524                 return false;
1525             }
1526 
1527             if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1528             {
1529                 context->handleError(
1530                     InvalidValue()
1531                     << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
1532                 return false;
1533             }
1534             break;
1535         }
1536         case BufferBinding::AtomicCounter:
1537         {
1538             if (context->getClientVersion() < ES_3_1)
1539             {
1540                 context->handleError(InvalidEnum()
1541                                      << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
1542                 return false;
1543             }
1544             if (index >= caps.maxAtomicCounterBufferBindings)
1545             {
1546                 context->handleError(InvalidValue() << "index is greater than or equal to the "
1547                                                        "number of ATOMIC_COUNTER_BUFFER "
1548                                                        "indexed binding points.");
1549                 return false;
1550             }
1551             if (buffer != 0 && (offset % 4) != 0)
1552             {
1553                 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
1554                 return false;
1555             }
1556             break;
1557         }
1558         case BufferBinding::ShaderStorage:
1559         {
1560             if (context->getClientVersion() < ES_3_1)
1561             {
1562                 context->handleError(InvalidEnum()
1563                                      << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
1564                 return false;
1565             }
1566             if (index >= caps.maxShaderStorageBufferBindings)
1567             {
1568                 context->handleError(InvalidValue() << "index is greater than or equal to the "
1569                                                        "number of SHADER_STORAGE_BUFFER "
1570                                                        "indexed binding points.");
1571                 return false;
1572             }
1573             if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1574             {
1575                 context->handleError(InvalidValue() << "offset must be multiple of value of "
1576                                                        "SHADER_STORAGE_BUFFER_OFFSET_"
1577                                                        "ALIGNMENT.");
1578                 return false;
1579             }
1580             break;
1581         }
1582         default:
1583             context->handleError(InvalidEnum() << "the target is not supported.");
1584             return false;
1585     }
1586 
1587     return true;
1588 }
1589 
ValidateBindBufferBase(Context * context,BufferBinding target,GLuint index,GLuint buffer)1590 bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
1591 {
1592     return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1593 }
1594 
ValidateBindBufferRange(Context * context,BufferBinding target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)1595 bool ValidateBindBufferRange(Context *context,
1596                              BufferBinding target,
1597                              GLuint index,
1598                              GLuint buffer,
1599                              GLintptr offset,
1600                              GLsizeiptr size)
1601 {
1602     if (buffer != 0 && size <= 0)
1603     {
1604         context->handleError(InvalidValue()
1605                              << "buffer is non-zero and size is less than or equal to zero.");
1606         return false;
1607     }
1608     return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1609 }
1610 
ValidateProgramBinary(Context * context,GLuint program,GLenum binaryFormat,const void * binary,GLint length)1611 bool ValidateProgramBinary(Context *context,
1612                            GLuint program,
1613                            GLenum binaryFormat,
1614                            const void *binary,
1615                            GLint length)
1616 {
1617     if (context->getClientMajorVersion() < 3)
1618     {
1619         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1620         return false;
1621     }
1622 
1623     return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1624 }
1625 
ValidateGetProgramBinary(Context * context,GLuint program,GLsizei bufSize,GLsizei * length,GLenum * binaryFormat,void * binary)1626 bool ValidateGetProgramBinary(Context *context,
1627                               GLuint program,
1628                               GLsizei bufSize,
1629                               GLsizei *length,
1630                               GLenum *binaryFormat,
1631                               void *binary)
1632 {
1633     if (context->getClientMajorVersion() < 3)
1634     {
1635         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1636         return false;
1637     }
1638 
1639     return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1640 }
1641 
ValidateProgramParameteri(Context * context,GLuint program,GLenum pname,GLint value)1642 bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
1643 {
1644     if (context->getClientMajorVersion() < 3)
1645     {
1646         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1647         return false;
1648     }
1649 
1650     if (GetValidProgram(context, program) == nullptr)
1651     {
1652         return false;
1653     }
1654 
1655     switch (pname)
1656     {
1657         case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
1658             if (value != GL_FALSE && value != GL_TRUE)
1659             {
1660                 context->handleError(InvalidValue()
1661                                      << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
1662                 return false;
1663             }
1664             break;
1665 
1666         case GL_PROGRAM_SEPARABLE:
1667             if (context->getClientVersion() < ES_3_1)
1668             {
1669                 context->handleError(InvalidEnum()
1670                                      << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
1671                 return false;
1672             }
1673 
1674             if (value != GL_FALSE && value != GL_TRUE)
1675             {
1676                 context->handleError(InvalidValue()
1677                                      << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
1678                 return false;
1679             }
1680             break;
1681 
1682         default:
1683             context->handleError(InvalidEnum()
1684                                  << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
1685             return false;
1686     }
1687 
1688     return true;
1689 }
1690 
ValidateBlitFramebuffer(Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1691 bool ValidateBlitFramebuffer(Context *context,
1692                              GLint srcX0,
1693                              GLint srcY0,
1694                              GLint srcX1,
1695                              GLint srcY1,
1696                              GLint dstX0,
1697                              GLint dstY0,
1698                              GLint dstX1,
1699                              GLint dstY1,
1700                              GLbitfield mask,
1701                              GLenum filter)
1702 {
1703     if (context->getClientMajorVersion() < 3)
1704     {
1705         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1706         return false;
1707     }
1708 
1709     return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1710                                              dstX1, dstY1, mask, filter);
1711 }
1712 
ValidateClearBufferiv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLint * value)1713 bool ValidateClearBufferiv(ValidationContext *context,
1714                            GLenum buffer,
1715                            GLint drawbuffer,
1716                            const GLint *value)
1717 {
1718     switch (buffer)
1719     {
1720         case GL_COLOR:
1721             if (drawbuffer < 0 ||
1722                 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1723             {
1724                 context->handleError(InvalidValue());
1725                 return false;
1726             }
1727             if (context->getExtensions().webglCompatibility)
1728             {
1729                 constexpr GLenum validComponentTypes[] = {GL_INT};
1730                 if (!ValidateWebGLFramebufferAttachmentClearType(
1731                         context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1732                 {
1733                     return false;
1734                 }
1735             }
1736             break;
1737 
1738         case GL_STENCIL:
1739             if (drawbuffer != 0)
1740             {
1741                 context->handleError(InvalidValue());
1742                 return false;
1743             }
1744             break;
1745 
1746         default:
1747             context->handleError(InvalidEnum());
1748             return false;
1749     }
1750 
1751     return ValidateClearBuffer(context);
1752 }
1753 
ValidateClearBufferuiv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLuint * value)1754 bool ValidateClearBufferuiv(ValidationContext *context,
1755                             GLenum buffer,
1756                             GLint drawbuffer,
1757                             const GLuint *value)
1758 {
1759     switch (buffer)
1760     {
1761         case GL_COLOR:
1762             if (drawbuffer < 0 ||
1763                 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1764             {
1765                 context->handleError(InvalidValue());
1766                 return false;
1767             }
1768             if (context->getExtensions().webglCompatibility)
1769             {
1770                 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1771                 if (!ValidateWebGLFramebufferAttachmentClearType(
1772                         context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1773                 {
1774                     return false;
1775                 }
1776             }
1777             break;
1778 
1779         default:
1780             context->handleError(InvalidEnum());
1781             return false;
1782     }
1783 
1784     return ValidateClearBuffer(context);
1785 }
1786 
ValidateClearBufferfv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLfloat * value)1787 bool ValidateClearBufferfv(ValidationContext *context,
1788                            GLenum buffer,
1789                            GLint drawbuffer,
1790                            const GLfloat *value)
1791 {
1792     switch (buffer)
1793     {
1794         case GL_COLOR:
1795             if (drawbuffer < 0 ||
1796                 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1797             {
1798                 context->handleError(InvalidValue());
1799                 return false;
1800             }
1801             if (context->getExtensions().webglCompatibility)
1802             {
1803                 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1804                                                           GL_SIGNED_NORMALIZED};
1805                 if (!ValidateWebGLFramebufferAttachmentClearType(
1806                         context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1807                 {
1808                     return false;
1809                 }
1810             }
1811             break;
1812 
1813         case GL_DEPTH:
1814             if (drawbuffer != 0)
1815             {
1816                 context->handleError(InvalidValue());
1817                 return false;
1818             }
1819             break;
1820 
1821         default:
1822             context->handleError(InvalidEnum());
1823             return false;
1824     }
1825 
1826     return ValidateClearBuffer(context);
1827 }
1828 
ValidateClearBufferfi(ValidationContext * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)1829 bool ValidateClearBufferfi(ValidationContext *context,
1830                            GLenum buffer,
1831                            GLint drawbuffer,
1832                            GLfloat depth,
1833                            GLint stencil)
1834 {
1835     switch (buffer)
1836     {
1837         case GL_DEPTH_STENCIL:
1838             if (drawbuffer != 0)
1839             {
1840                 context->handleError(InvalidValue());
1841                 return false;
1842             }
1843             break;
1844 
1845         default:
1846             context->handleError(InvalidEnum());
1847             return false;
1848     }
1849 
1850     return ValidateClearBuffer(context);
1851 }
1852 
ValidateDrawBuffers(ValidationContext * context,GLsizei n,const GLenum * bufs)1853 bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1854 {
1855     if (context->getClientMajorVersion() < 3)
1856     {
1857         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1858         return false;
1859     }
1860 
1861     return ValidateDrawBuffersBase(context, n, bufs);
1862 }
1863 
ValidateCopyTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)1864 bool ValidateCopyTexSubImage3D(Context *context,
1865                                GLenum target,
1866                                GLint level,
1867                                GLint xoffset,
1868                                GLint yoffset,
1869                                GLint zoffset,
1870                                GLint x,
1871                                GLint y,
1872                                GLsizei width,
1873                                GLsizei height)
1874 {
1875     if (context->getClientMajorVersion() < 3)
1876     {
1877         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1878         return false;
1879     }
1880 
1881     return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1882                                                yoffset, zoffset, x, y, width, height, 0);
1883 }
1884 
ValidateTexImage3D(Context * context,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)1885 bool ValidateTexImage3D(Context *context,
1886                         GLenum target,
1887                         GLint level,
1888                         GLint internalformat,
1889                         GLsizei width,
1890                         GLsizei height,
1891                         GLsizei depth,
1892                         GLint border,
1893                         GLenum format,
1894                         GLenum type,
1895                         const void *pixels)
1896 {
1897     if (context->getClientMajorVersion() < 3)
1898     {
1899         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1900         return false;
1901     }
1902 
1903     return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1904                                            0, 0, width, height, depth, border, format, type, -1,
1905                                            pixels);
1906 }
1907 
ValidateTexImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1908 bool ValidateTexImage3DRobustANGLE(Context *context,
1909                                    GLenum target,
1910                                    GLint level,
1911                                    GLint internalformat,
1912                                    GLsizei width,
1913                                    GLsizei height,
1914                                    GLsizei depth,
1915                                    GLint border,
1916                                    GLenum format,
1917                                    GLenum type,
1918                                    GLsizei bufSize,
1919                                    const void *pixels)
1920 {
1921     if (context->getClientMajorVersion() < 3)
1922     {
1923         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1924         return false;
1925     }
1926 
1927     if (!ValidateRobustEntryPoint(context, bufSize))
1928     {
1929         return false;
1930     }
1931 
1932     return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1933                                            0, 0, width, height, depth, border, format, type,
1934                                            bufSize, pixels);
1935 }
1936 
ValidateTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)1937 bool ValidateTexSubImage3D(Context *context,
1938                            GLenum target,
1939                            GLint level,
1940                            GLint xoffset,
1941                            GLint yoffset,
1942                            GLint zoffset,
1943                            GLsizei width,
1944                            GLsizei height,
1945                            GLsizei depth,
1946                            GLenum format,
1947                            GLenum type,
1948                            const void *pixels)
1949 {
1950     if (context->getClientMajorVersion() < 3)
1951     {
1952         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1953         return false;
1954     }
1955 
1956     return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1957                                            yoffset, zoffset, width, height, depth, 0, format, type,
1958                                            -1, pixels);
1959 }
1960 
ValidateTexSubImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1961 bool ValidateTexSubImage3DRobustANGLE(Context *context,
1962                                       GLenum target,
1963                                       GLint level,
1964                                       GLint xoffset,
1965                                       GLint yoffset,
1966                                       GLint zoffset,
1967                                       GLsizei width,
1968                                       GLsizei height,
1969                                       GLsizei depth,
1970                                       GLenum format,
1971                                       GLenum type,
1972                                       GLsizei bufSize,
1973                                       const void *pixels)
1974 {
1975     if (context->getClientMajorVersion() < 3)
1976     {
1977         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1978         return false;
1979     }
1980 
1981     if (!ValidateRobustEntryPoint(context, bufSize))
1982     {
1983         return false;
1984     }
1985 
1986     return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1987                                            yoffset, zoffset, width, height, depth, 0, format, type,
1988                                            bufSize, pixels);
1989 }
1990 
ValidateCompressedTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)1991 bool ValidateCompressedTexSubImage3D(Context *context,
1992                                      GLenum target,
1993                                      GLint level,
1994                                      GLint xoffset,
1995                                      GLint yoffset,
1996                                      GLint zoffset,
1997                                      GLsizei width,
1998                                      GLsizei height,
1999                                      GLsizei depth,
2000                                      GLenum format,
2001                                      GLsizei imageSize,
2002                                      const void *data)
2003 {
2004     if (context->getClientMajorVersion() < 3)
2005     {
2006         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2007         return false;
2008     }
2009 
2010     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2011     if (!formatInfo.compressed)
2012     {
2013         context->handleError(InvalidEnum() << "Not a valid compressed texture format");
2014         return false;
2015     }
2016 
2017     auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
2018     if (blockSizeOrErr.isError())
2019     {
2020         context->handleError(blockSizeOrErr.getError());
2021         return false;
2022     }
2023     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
2024     {
2025         context->handleError(InvalidValue());
2026         return false;
2027     }
2028 
2029     if (!data)
2030     {
2031         context->handleError(InvalidValue());
2032         return false;
2033     }
2034 
2035     return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2036                                            yoffset, zoffset, width, height, depth, 0, format,
2037                                            GL_NONE, -1, data);
2038 }
ValidateCompressedTexSubImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2039 bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2040                                                 GLenum target,
2041                                                 GLint level,
2042                                                 GLint xoffset,
2043                                                 GLint yoffset,
2044                                                 GLint zoffset,
2045                                                 GLsizei width,
2046                                                 GLsizei height,
2047                                                 GLsizei depth,
2048                                                 GLenum format,
2049                                                 GLsizei imageSize,
2050                                                 GLsizei dataSize,
2051                                                 const void *data)
2052 {
2053     if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2054     {
2055         return false;
2056     }
2057 
2058     return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2059                                            height, depth, format, imageSize, data);
2060 }
2061 
ValidateGenQueries(Context * context,GLint n,GLuint *)2062 bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2063 {
2064     return ValidateGenOrDeleteES3(context, n);
2065 }
2066 
ValidateDeleteQueries(Context * context,GLint n,const GLuint *)2067 bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2068 {
2069     return ValidateGenOrDeleteES3(context, n);
2070 }
2071 
ValidateGenSamplers(Context * context,GLint count,GLuint *)2072 bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2073 {
2074     return ValidateGenOrDeleteCountES3(context, count);
2075 }
2076 
ValidateDeleteSamplers(Context * context,GLint count,const GLuint *)2077 bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2078 {
2079     return ValidateGenOrDeleteCountES3(context, count);
2080 }
2081 
ValidateGenTransformFeedbacks(Context * context,GLint n,GLuint *)2082 bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2083 {
2084     return ValidateGenOrDeleteES3(context, n);
2085 }
2086 
ValidateDeleteTransformFeedbacks(Context * context,GLint n,const GLuint * ids)2087 bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2088 {
2089     if (!ValidateGenOrDeleteES3(context, n))
2090     {
2091         return false;
2092     }
2093     for (GLint i = 0; i < n; ++i)
2094     {
2095         auto *transformFeedback = context->getTransformFeedback(ids[i]);
2096         if (transformFeedback != nullptr && transformFeedback->isActive())
2097         {
2098             // ES 3.0.4 section 2.15.1 page 86
2099             context->handleError(InvalidOperation()
2100                                  << "Attempt to delete active transform feedback.");
2101             return false;
2102         }
2103     }
2104     return true;
2105 }
2106 
ValidateGenVertexArrays(Context * context,GLint n,GLuint *)2107 bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2108 {
2109     return ValidateGenOrDeleteES3(context, n);
2110 }
2111 
ValidateDeleteVertexArrays(Context * context,GLint n,const GLuint *)2112 bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2113 {
2114     return ValidateGenOrDeleteES3(context, n);
2115 }
2116 
ValidateBeginTransformFeedback(Context * context,GLenum primitiveMode)2117 bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2118 {
2119     if (context->getClientMajorVersion() < 3)
2120     {
2121         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2122         return false;
2123     }
2124     switch (primitiveMode)
2125     {
2126         case GL_TRIANGLES:
2127         case GL_LINES:
2128         case GL_POINTS:
2129             break;
2130 
2131         default:
2132             context->handleError(InvalidEnum() << "Invalid primitive mode.");
2133             return false;
2134     }
2135 
2136     TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2137     ASSERT(transformFeedback != nullptr);
2138 
2139     if (transformFeedback->isActive())
2140     {
2141         context->handleError(InvalidOperation() << "Transform feedback is already active.");
2142         return false;
2143     }
2144 
2145     for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2146     {
2147         const auto &buffer = transformFeedback->getIndexedBuffer(i);
2148         if (buffer.get() && buffer->isMapped())
2149         {
2150             context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2151             return false;
2152         }
2153     }
2154 
2155     Program *program = context->getGLState().getProgram();
2156 
2157     if (!program)
2158     {
2159         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2160         return false;
2161     }
2162 
2163     if (program->getTransformFeedbackVaryingCount() == 0)
2164     {
2165         ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2166         return false;
2167     }
2168 
2169     return true;
2170 }
2171 
ValidateGetBufferPointerv(Context * context,BufferBinding target,GLenum pname,void ** params)2172 bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
2173 {
2174     return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2175 }
2176 
ValidateGetBufferPointervRobustANGLE(Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,GLsizei * length,void ** params)2177 bool ValidateGetBufferPointervRobustANGLE(Context *context,
2178                                           BufferBinding target,
2179                                           GLenum pname,
2180                                           GLsizei bufSize,
2181                                           GLsizei *length,
2182                                           void **params)
2183 {
2184     if (!ValidateRobustEntryPoint(context, bufSize))
2185     {
2186         return false;
2187     }
2188 
2189     if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2190     {
2191         return false;
2192     }
2193 
2194     if (!ValidateRobustBufferSize(context, bufSize, *length))
2195     {
2196         return false;
2197     }
2198 
2199     return true;
2200 }
2201 
ValidateUnmapBuffer(Context * context,BufferBinding target)2202 bool ValidateUnmapBuffer(Context *context, BufferBinding target)
2203 {
2204     if (context->getClientMajorVersion() < 3)
2205     {
2206         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2207         return false;
2208     }
2209 
2210     return ValidateUnmapBufferBase(context, target);
2211 }
2212 
ValidateMapBufferRange(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)2213 bool ValidateMapBufferRange(Context *context,
2214                             BufferBinding target,
2215                             GLintptr offset,
2216                             GLsizeiptr length,
2217                             GLbitfield access)
2218 {
2219     if (context->getClientMajorVersion() < 3)
2220     {
2221         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2222         return false;
2223     }
2224 
2225     return ValidateMapBufferRangeBase(context, target, offset, length, access);
2226 }
2227 
ValidateFlushMappedBufferRange(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)2228 bool ValidateFlushMappedBufferRange(Context *context,
2229                                     BufferBinding target,
2230                                     GLintptr offset,
2231                                     GLsizeiptr length)
2232 {
2233     if (context->getClientMajorVersion() < 3)
2234     {
2235         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2236         return false;
2237     }
2238 
2239     return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2240 }
2241 
ValidateIndexedStateQuery(ValidationContext * context,GLenum pname,GLuint index,GLsizei * length)2242 bool ValidateIndexedStateQuery(ValidationContext *context,
2243                                GLenum pname,
2244                                GLuint index,
2245                                GLsizei *length)
2246 {
2247     if (length)
2248     {
2249         *length = 0;
2250     }
2251 
2252     GLenum nativeType;
2253     unsigned int numParams;
2254     if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2255     {
2256         context->handleError(InvalidEnum());
2257         return false;
2258     }
2259 
2260     const Caps &caps = context->getCaps();
2261     switch (pname)
2262     {
2263         case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2264         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2265         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2266             if (index >= caps.maxTransformFeedbackSeparateAttributes)
2267             {
2268                 context->handleError(InvalidValue());
2269                 return false;
2270             }
2271             break;
2272 
2273         case GL_UNIFORM_BUFFER_START:
2274         case GL_UNIFORM_BUFFER_SIZE:
2275         case GL_UNIFORM_BUFFER_BINDING:
2276             if (index >= caps.maxUniformBufferBindings)
2277             {
2278                 context->handleError(InvalidValue());
2279                 return false;
2280             }
2281             break;
2282 
2283         case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2284         case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2285             if (index >= 3u)
2286             {
2287                 context->handleError(InvalidValue());
2288                 return false;
2289             }
2290             break;
2291 
2292         case GL_ATOMIC_COUNTER_BUFFER_START:
2293         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2294         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2295             if (context->getClientVersion() < ES_3_1)
2296             {
2297                 context->handleError(
2298                     InvalidEnum()
2299                     << "Atomic Counter buffers are not supported in this version of GL");
2300                 return false;
2301             }
2302             if (index >= caps.maxAtomicCounterBufferBindings)
2303             {
2304                 context->handleError(
2305                     InvalidValue()
2306                     << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
2307                 return false;
2308             }
2309             break;
2310 
2311         case GL_SHADER_STORAGE_BUFFER_START:
2312         case GL_SHADER_STORAGE_BUFFER_SIZE:
2313         case GL_SHADER_STORAGE_BUFFER_BINDING:
2314             if (context->getClientVersion() < ES_3_1)
2315             {
2316                 context->handleError(
2317                     InvalidEnum()
2318                     << "Shader storage buffers are not supported in this version of GL");
2319                 return false;
2320             }
2321             if (index >= caps.maxShaderStorageBufferBindings)
2322             {
2323                 context->handleError(
2324                     InvalidValue()
2325                     << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
2326                 return false;
2327             }
2328             break;
2329 
2330         case GL_VERTEX_BINDING_BUFFER:
2331         case GL_VERTEX_BINDING_DIVISOR:
2332         case GL_VERTEX_BINDING_OFFSET:
2333         case GL_VERTEX_BINDING_STRIDE:
2334             if (context->getClientVersion() < ES_3_1)
2335             {
2336                 context->handleError(
2337                     InvalidEnum()
2338                     << "Vertex Attrib Bindings are not supported in this version of GL");
2339                 return false;
2340             }
2341             if (index >= caps.maxVertexAttribBindings)
2342             {
2343                 context->handleError(
2344                     InvalidValue()
2345                     << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
2346                 return false;
2347             }
2348             break;
2349         case GL_SAMPLE_MASK_VALUE:
2350             if (context->getClientVersion() < ES_3_1)
2351             {
2352                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2353                 return false;
2354             }
2355             if (index >= caps.maxSampleMaskWords)
2356             {
2357                 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2358                 return false;
2359             }
2360             break;
2361         default:
2362             context->handleError(InvalidEnum());
2363             return false;
2364     }
2365 
2366     if (length)
2367     {
2368         *length = 1;
2369     }
2370 
2371     return true;
2372 }
2373 
ValidateGetIntegeri_v(ValidationContext * context,GLenum target,GLuint index,GLint * data)2374 bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2375 {
2376     if (context->getClientVersion() < ES_3_0)
2377     {
2378         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2379         return false;
2380     }
2381     return ValidateIndexedStateQuery(context, target, index, nullptr);
2382 }
2383 
ValidateGetIntegeri_vRobustANGLE(ValidationContext * context,GLenum target,GLuint index,GLsizei bufSize,GLsizei * length,GLint * data)2384 bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2385                                       GLenum target,
2386                                       GLuint index,
2387                                       GLsizei bufSize,
2388                                       GLsizei *length,
2389                                       GLint *data)
2390 {
2391     if (context->getClientVersion() < ES_3_0)
2392     {
2393         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2394         return false;
2395     }
2396 
2397     if (!ValidateRobustEntryPoint(context, bufSize))
2398     {
2399         return false;
2400     }
2401 
2402     if (!ValidateIndexedStateQuery(context, target, index, length))
2403     {
2404         return false;
2405     }
2406 
2407     if (!ValidateRobustBufferSize(context, bufSize, *length))
2408     {
2409         return false;
2410     }
2411 
2412     return true;
2413 }
2414 
ValidateGetInteger64i_v(ValidationContext * context,GLenum target,GLuint index,GLint64 * data)2415 bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2416 {
2417     if (context->getClientVersion() < ES_3_0)
2418     {
2419         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2420         return false;
2421     }
2422     return ValidateIndexedStateQuery(context, target, index, nullptr);
2423 }
2424 
ValidateGetInteger64i_vRobustANGLE(ValidationContext * context,GLenum target,GLuint index,GLsizei bufSize,GLsizei * length,GLint64 * data)2425 bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2426                                         GLenum target,
2427                                         GLuint index,
2428                                         GLsizei bufSize,
2429                                         GLsizei *length,
2430                                         GLint64 *data)
2431 {
2432     if (context->getClientVersion() < ES_3_0)
2433     {
2434         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2435         return false;
2436     }
2437 
2438     if (!ValidateRobustEntryPoint(context, bufSize))
2439     {
2440         return false;
2441     }
2442 
2443     if (!ValidateIndexedStateQuery(context, target, index, length))
2444     {
2445         return false;
2446     }
2447 
2448     if (!ValidateRobustBufferSize(context, bufSize, *length))
2449     {
2450         return false;
2451     }
2452 
2453     return true;
2454 }
2455 
ValidateCopyBufferSubData(ValidationContext * context,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)2456 bool ValidateCopyBufferSubData(ValidationContext *context,
2457                                BufferBinding readTarget,
2458                                BufferBinding writeTarget,
2459                                GLintptr readOffset,
2460                                GLintptr writeOffset,
2461                                GLsizeiptr size)
2462 {
2463     if (context->getClientMajorVersion() < 3)
2464     {
2465         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2466         return false;
2467     }
2468 
2469     if (!ValidBufferType(context, readTarget) || !ValidBufferType(context, writeTarget))
2470     {
2471         context->handleError(InvalidEnum() << "Invalid buffer target");
2472         return false;
2473     }
2474 
2475     Buffer *readBuffer  = context->getGLState().getTargetBuffer(readTarget);
2476     Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2477 
2478     if (!readBuffer || !writeBuffer)
2479     {
2480         context->handleError(InvalidOperation() << "No buffer bound to target");
2481         return false;
2482     }
2483 
2484     // Verify that readBuffer and writeBuffer are not currently mapped
2485     if (readBuffer->isMapped() || writeBuffer->isMapped())
2486     {
2487         context->handleError(InvalidOperation()
2488                              << "Cannot call CopyBufferSubData on a mapped buffer");
2489         return false;
2490     }
2491 
2492     CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2493     CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2494     CheckedNumeric<GLintptr> checkedSize(size);
2495 
2496     auto checkedReadSum  = checkedReadOffset + checkedSize;
2497     auto checkedWriteSum = checkedWriteOffset + checkedSize;
2498 
2499     if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2500         !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2501         !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
2502     {
2503         context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
2504         return false;
2505     }
2506 
2507     if (readOffset < 0 || writeOffset < 0 || size < 0)
2508     {
2509         context->handleError(InvalidValue()
2510                              << "readOffset, writeOffset and size must all be non-negative");
2511         return false;
2512     }
2513 
2514     if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2515         checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2516     {
2517         context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
2518         return false;
2519     }
2520 
2521     if (readBuffer == writeBuffer)
2522     {
2523         auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2524         if (!checkedOffsetDiff.IsValid())
2525         {
2526             // This shold not be possible.
2527             UNREACHABLE();
2528             context->handleError(InvalidValue()
2529                                  << "Integer overflow when validating same buffer copy.");
2530             return false;
2531         }
2532 
2533         if (checkedOffsetDiff.ValueOrDie() < size)
2534         {
2535             context->handleError(InvalidValue());
2536             return false;
2537         }
2538     }
2539 
2540     return true;
2541 }
2542 
ValidateGetStringi(Context * context,GLenum name,GLuint index)2543 bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2544 {
2545     if (context->getClientMajorVersion() < 3)
2546     {
2547         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2548         return false;
2549     }
2550 
2551     switch (name)
2552     {
2553         case GL_EXTENSIONS:
2554             if (index >= context->getExtensionStringCount())
2555             {
2556                 context->handleError(InvalidValue()
2557                                      << "index must be less than the number of extension strings.");
2558                 return false;
2559             }
2560             break;
2561 
2562         case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2563             if (!context->getExtensions().requestExtension)
2564             {
2565                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
2566                 return false;
2567             }
2568             if (index >= context->getRequestableExtensionStringCount())
2569             {
2570                 context->handleError(
2571                     InvalidValue()
2572                     << "index must be less than the number of requestable extension strings.");
2573                 return false;
2574             }
2575             break;
2576 
2577         default:
2578             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
2579             return false;
2580     }
2581 
2582     return true;
2583 }
2584 
ValidateRenderbufferStorageMultisample(ValidationContext * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)2585 bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2586                                             GLenum target,
2587                                             GLsizei samples,
2588                                             GLenum internalformat,
2589                                             GLsizei width,
2590                                             GLsizei height)
2591 {
2592     if (context->getClientMajorVersion() < 3)
2593     {
2594         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2595         return false;
2596     }
2597 
2598     if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2599                                                    height))
2600     {
2601         return false;
2602     }
2603 
2604     // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2605     // format if samples is greater than zero.
2606     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
2607     if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2608         samples > 0)
2609     {
2610         context->handleError(InvalidOperation());
2611         return false;
2612     }
2613 
2614     // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2615     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2616     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2617     {
2618         context->handleError(
2619             InvalidOperation()
2620             << "Samples must not be greater than maximum supported value for the format.");
2621         return false;
2622     }
2623 
2624     return true;
2625 }
2626 
ValidateVertexAttribIPointer(ValidationContext * context,GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer)2627 bool ValidateVertexAttribIPointer(ValidationContext *context,
2628                                   GLuint index,
2629                                   GLint size,
2630                                   GLenum type,
2631                                   GLsizei stride,
2632                                   const void *pointer)
2633 {
2634     if (context->getClientMajorVersion() < 3)
2635     {
2636         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2637         return false;
2638     }
2639 
2640     if (!ValidateVertexFormatBase(context, index, size, type, true))
2641     {
2642         return false;
2643     }
2644 
2645     if (stride < 0)
2646     {
2647         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
2648         return false;
2649     }
2650 
2651     const Caps &caps = context->getCaps();
2652     if (context->getClientVersion() >= ES_3_1)
2653     {
2654         if (stride > caps.maxVertexAttribStride)
2655         {
2656             context->handleError(InvalidValue()
2657                                  << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
2658             return false;
2659         }
2660 
2661         // [OpenGL ES 3.1] Section 10.3.1 page 245:
2662         // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2663         // validation should be inherited.
2664         if (index >= caps.maxVertexAttribBindings)
2665         {
2666             context->handleError(InvalidValue()
2667                                  << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
2668             return false;
2669         }
2670     }
2671 
2672     // [OpenGL ES 3.0.2] Section 2.8 page 24:
2673     // An INVALID_OPERATION error is generated when a non-zero vertex array object
2674     // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2675     // and the pointer argument is not NULL.
2676     if (context->getGLState().getVertexArrayId() != 0 &&
2677         context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
2678     {
2679         context
2680             ->handleError(InvalidOperation()
2681                           << "Client data cannot be used with a non-default vertex array object.");
2682         return false;
2683     }
2684 
2685     if (context->getExtensions().webglCompatibility)
2686     {
2687         if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2688         {
2689             return false;
2690         }
2691     }
2692 
2693     return true;
2694 }
2695 
ValidateGetSynciv(Context * context,GLsync sync,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)2696 bool ValidateGetSynciv(Context *context,
2697                        GLsync sync,
2698                        GLenum pname,
2699                        GLsizei bufSize,
2700                        GLsizei *length,
2701                        GLint *values)
2702 {
2703     if (context->getClientMajorVersion() < 3)
2704     {
2705         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2706         return false;
2707     }
2708 
2709     if (bufSize < 0)
2710     {
2711         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
2712         return false;
2713     }
2714 
2715     Sync *syncObject = context->getSync(sync);
2716     if (!syncObject)
2717     {
2718         context->handleError(InvalidValue() << "Invalid sync object.");
2719         return false;
2720     }
2721 
2722     switch (pname)
2723     {
2724         case GL_OBJECT_TYPE:
2725         case GL_SYNC_CONDITION:
2726         case GL_SYNC_FLAGS:
2727         case GL_SYNC_STATUS:
2728             break;
2729 
2730         default:
2731             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
2732             return false;
2733     }
2734 
2735     return true;
2736 }
2737 
ValidateDrawElementsInstanced(ValidationContext * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei instanceCount)2738 bool ValidateDrawElementsInstanced(ValidationContext *context,
2739                                    GLenum mode,
2740                                    GLsizei count,
2741                                    GLenum type,
2742                                    const void *indices,
2743                                    GLsizei instanceCount)
2744 {
2745     if (context->getClientMajorVersion() < 3)
2746     {
2747         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2748         return false;
2749     }
2750 
2751     return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2752 }
2753 
ValidateFramebufferTextureMultiviewLayeredANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint baseViewIndex,GLsizei numViews)2754 bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2755                                                      GLenum target,
2756                                                      GLenum attachment,
2757                                                      GLuint texture,
2758                                                      GLint level,
2759                                                      GLint baseViewIndex,
2760                                                      GLsizei numViews)
2761 {
2762 
2763     if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2764                                                       numViews))
2765     {
2766         return false;
2767     }
2768 
2769     if (texture != 0)
2770     {
2771         if (baseViewIndex < 0)
2772         {
2773             context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2774             return false;
2775         }
2776 
2777         Texture *tex = context->getTexture(texture);
2778         ASSERT(tex);
2779 
2780         switch (tex->getTarget())
2781         {
2782             case GL_TEXTURE_2D_ARRAY:
2783             {
2784                 const Caps &caps = context->getCaps();
2785                 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2786                 {
2787                     context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2788                                                            "greater than "
2789                                                            "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2790                     return false;
2791                 }
2792             }
2793             break;
2794             default:
2795                 context->handleError(InvalidOperation()
2796                                      << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2797                 return false;
2798         }
2799 
2800         if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2801         {
2802             return false;
2803         }
2804     }
2805 
2806     return true;
2807 }
2808 
ValidateFramebufferTextureMultiviewSideBySideANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLsizei numViews,const GLint * viewportOffsets)2809 bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2810                                                         GLenum target,
2811                                                         GLenum attachment,
2812                                                         GLuint texture,
2813                                                         GLint level,
2814                                                         GLsizei numViews,
2815                                                         const GLint *viewportOffsets)
2816 {
2817     if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2818                                                       numViews))
2819     {
2820         return false;
2821     }
2822 
2823     if (texture != 0)
2824     {
2825         const GLsizei numViewportOffsetValues = numViews * 2;
2826         for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2827         {
2828             if (viewportOffsets[i] < 0)
2829             {
2830                 context->handleError(InvalidValue()
2831                                      << "viewportOffsets cannot contain negative values.");
2832                 return false;
2833             }
2834         }
2835 
2836         Texture *tex = context->getTexture(texture);
2837         ASSERT(tex);
2838 
2839         switch (tex->getTarget())
2840         {
2841             case GL_TEXTURE_2D:
2842                 break;
2843             default:
2844                 context->handleError(InvalidOperation()
2845                                      << "Texture's target must be GL_TEXTURE_2D.");
2846                 return false;
2847         }
2848 
2849         if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2850         {
2851             return false;
2852         }
2853     }
2854 
2855     return true;
2856 }
2857 
ValidateUniform1ui(Context * context,GLint location,GLuint v0)2858 bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2859 {
2860     return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2861 }
2862 
ValidateUniform2ui(Context * context,GLint location,GLuint v0,GLuint v1)2863 bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2864 {
2865     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2866 }
2867 
ValidateUniform3ui(Context * context,GLint location,GLuint v0,GLuint v1,GLuint v2)2868 bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2869 {
2870     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2871 }
2872 
ValidateUniform4ui(Context * context,GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)2873 bool ValidateUniform4ui(Context *context,
2874                         GLint location,
2875                         GLuint v0,
2876                         GLuint v1,
2877                         GLuint v2,
2878                         GLuint v3)
2879 {
2880     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2881 }
2882 
ValidateUniform1uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2883 bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2884 {
2885     return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2886 }
2887 
ValidateUniform2uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2888 bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2889 {
2890     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2891 }
2892 
ValidateUniform3uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2893 bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2894 {
2895     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2896 }
2897 
ValidateUniform4uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2898 bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2899 {
2900     return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2901 }
2902 
ValidateIsQuery(Context * context,GLuint id)2903 bool ValidateIsQuery(Context *context, GLuint id)
2904 {
2905     if (context->getClientMajorVersion() < 3)
2906     {
2907         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2908         return false;
2909     }
2910 
2911     return true;
2912 }
2913 
ValidateUniformMatrix2x3fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2914 bool ValidateUniformMatrix2x3fv(Context *context,
2915                                 GLint location,
2916                                 GLsizei count,
2917                                 GLboolean transpose,
2918                                 const GLfloat *value)
2919 {
2920     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2921 }
2922 
ValidateUniformMatrix3x2fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2923 bool ValidateUniformMatrix3x2fv(Context *context,
2924                                 GLint location,
2925                                 GLsizei count,
2926                                 GLboolean transpose,
2927                                 const GLfloat *value)
2928 {
2929     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2930 }
2931 
ValidateUniformMatrix2x4fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2932 bool ValidateUniformMatrix2x4fv(Context *context,
2933                                 GLint location,
2934                                 GLsizei count,
2935                                 GLboolean transpose,
2936                                 const GLfloat *value)
2937 {
2938     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2939 }
2940 
ValidateUniformMatrix4x2fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2941 bool ValidateUniformMatrix4x2fv(Context *context,
2942                                 GLint location,
2943                                 GLsizei count,
2944                                 GLboolean transpose,
2945                                 const GLfloat *value)
2946 {
2947     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2948 }
2949 
ValidateUniformMatrix3x4fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2950 bool ValidateUniformMatrix3x4fv(Context *context,
2951                                 GLint location,
2952                                 GLsizei count,
2953                                 GLboolean transpose,
2954                                 const GLfloat *value)
2955 {
2956     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2957 }
2958 
ValidateUniformMatrix4x3fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2959 bool ValidateUniformMatrix4x3fv(Context *context,
2960                                 GLint location,
2961                                 GLsizei count,
2962                                 GLboolean transpose,
2963                                 const GLfloat *value)
2964 {
2965     return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2966 }
2967 
ValidateEndTransformFeedback(Context * context)2968 bool ValidateEndTransformFeedback(Context *context)
2969 {
2970     if (context->getClientMajorVersion() < 3)
2971     {
2972         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2973         return false;
2974     }
2975 
2976     TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2977     ASSERT(transformFeedback != nullptr);
2978 
2979     if (!transformFeedback->isActive())
2980     {
2981         context->handleError(InvalidOperation());
2982         return false;
2983     }
2984 
2985     return true;
2986 }
2987 
ValidateTransformFeedbackVaryings(Context * context,GLuint program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2988 bool ValidateTransformFeedbackVaryings(Context *context,
2989                                        GLuint program,
2990                                        GLsizei count,
2991                                        const GLchar *const *varyings,
2992                                        GLenum bufferMode)
2993 {
2994     if (context->getClientMajorVersion() < 3)
2995     {
2996         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2997         return false;
2998     }
2999 
3000     if (count < 0)
3001     {
3002         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3003         return false;
3004     }
3005 
3006     switch (bufferMode)
3007     {
3008         case GL_INTERLEAVED_ATTRIBS:
3009             break;
3010         case GL_SEPARATE_ATTRIBS:
3011         {
3012             const Caps &caps = context->getCaps();
3013             if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3014             {
3015                 context->handleError(InvalidValue());
3016                 return false;
3017             }
3018             break;
3019         }
3020         default:
3021             context->handleError(InvalidEnum());
3022             return false;
3023     }
3024 
3025     Program *programObject = GetValidProgram(context, program);
3026     if (!programObject)
3027     {
3028         return false;
3029     }
3030 
3031     return true;
3032 }
3033 
ValidateGetTransformFeedbackVarying(Context * context,GLuint program,GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name)3034 bool ValidateGetTransformFeedbackVarying(Context *context,
3035                                          GLuint program,
3036                                          GLuint index,
3037                                          GLsizei bufSize,
3038                                          GLsizei *length,
3039                                          GLsizei *size,
3040                                          GLenum *type,
3041                                          GLchar *name)
3042 {
3043     if (context->getClientMajorVersion() < 3)
3044     {
3045         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3046         return false;
3047     }
3048 
3049     if (bufSize < 0)
3050     {
3051         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3052         return false;
3053     }
3054 
3055     Program *programObject = GetValidProgram(context, program);
3056     if (!programObject)
3057     {
3058         return false;
3059     }
3060 
3061     if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3062     {
3063         context->handleError(InvalidValue());
3064         return false;
3065     }
3066 
3067     return true;
3068 }
3069 
ValidateBindTransformFeedback(Context * context,GLenum target,GLuint id)3070 bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3071 {
3072     if (context->getClientMajorVersion() < 3)
3073     {
3074         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3075         return false;
3076     }
3077 
3078     switch (target)
3079     {
3080         case GL_TRANSFORM_FEEDBACK:
3081         {
3082             // Cannot bind a transform feedback object if the current one is started and not
3083             // paused (3.0.2 pg 85 section 2.14.1)
3084             TransformFeedback *curTransformFeedback =
3085                 context->getGLState().getCurrentTransformFeedback();
3086             if (curTransformFeedback && curTransformFeedback->isActive() &&
3087                 !curTransformFeedback->isPaused())
3088             {
3089                 context->handleError(InvalidOperation());
3090                 return false;
3091             }
3092 
3093             // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3094             // 2.14.1)
3095             if (!context->isTransformFeedbackGenerated(id))
3096             {
3097                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3098                 return false;
3099             }
3100         }
3101         break;
3102 
3103         default:
3104             context->handleError(InvalidEnum());
3105             return false;
3106     }
3107 
3108     return true;
3109 }
3110 
ValidateIsTransformFeedback(Context * context,GLuint id)3111 bool ValidateIsTransformFeedback(Context *context, GLuint id)
3112 {
3113     if (context->getClientMajorVersion() < 3)
3114     {
3115         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3116         return false;
3117     }
3118 
3119     return true;
3120 }
3121 
ValidatePauseTransformFeedback(Context * context)3122 bool ValidatePauseTransformFeedback(Context *context)
3123 {
3124     if (context->getClientMajorVersion() < 3)
3125     {
3126         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3127         return false;
3128     }
3129 
3130     TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3131     ASSERT(transformFeedback != nullptr);
3132 
3133     // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3134     if (!transformFeedback->isActive() || transformFeedback->isPaused())
3135     {
3136         context->handleError(InvalidOperation());
3137         return false;
3138     }
3139 
3140     return true;
3141 }
3142 
ValidateResumeTransformFeedback(Context * context)3143 bool ValidateResumeTransformFeedback(Context *context)
3144 {
3145     if (context->getClientMajorVersion() < 3)
3146     {
3147         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3148         return false;
3149     }
3150 
3151     TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3152     ASSERT(transformFeedback != nullptr);
3153 
3154     // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3155     if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3156     {
3157         context->handleError(InvalidOperation());
3158         return false;
3159     }
3160 
3161     return true;
3162 }
3163 
ValidateVertexAttribI4i(Context * context,GLuint index,GLint x,GLint y,GLint z,GLint w)3164 bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3165 {
3166     if (context->getClientMajorVersion() < 3)
3167     {
3168         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3169         return false;
3170     }
3171 
3172     return ValidateVertexAttribIndex(context, index);
3173 }
3174 
ValidateVertexAttribI4ui(Context * context,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)3175 bool ValidateVertexAttribI4ui(Context *context,
3176                               GLuint index,
3177                               GLuint x,
3178                               GLuint y,
3179                               GLuint z,
3180                               GLuint w)
3181 {
3182     if (context->getClientMajorVersion() < 3)
3183     {
3184         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3185         return false;
3186     }
3187 
3188     return ValidateVertexAttribIndex(context, index);
3189 }
3190 
ValidateVertexAttribI4iv(Context * context,GLuint index,const GLint * v)3191 bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3192 {
3193     if (context->getClientMajorVersion() < 3)
3194     {
3195         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3196         return false;
3197     }
3198 
3199     return ValidateVertexAttribIndex(context, index);
3200 }
3201 
ValidateVertexAttribI4uiv(Context * context,GLuint index,const GLuint * v)3202 bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3203 {
3204     if (context->getClientMajorVersion() < 3)
3205     {
3206         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3207         return false;
3208     }
3209 
3210     return ValidateVertexAttribIndex(context, index);
3211 }
3212 
ValidateGetFragDataLocation(Context * context,GLuint program,const GLchar * name)3213 bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3214 {
3215     if (context->getClientMajorVersion() < 3)
3216     {
3217         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3218         return false;
3219     }
3220 
3221     Program *programObject = GetValidProgram(context, program);
3222     if (!programObject)
3223     {
3224         return false;
3225     }
3226 
3227     if (!programObject->isLinked())
3228     {
3229         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3230         return false;
3231     }
3232 
3233     return true;
3234 }
3235 
ValidateGetUniformIndices(Context * context,GLuint program,GLsizei uniformCount,const GLchar * const * uniformNames,GLuint * uniformIndices)3236 bool ValidateGetUniformIndices(Context *context,
3237                                GLuint program,
3238                                GLsizei uniformCount,
3239                                const GLchar *const *uniformNames,
3240                                GLuint *uniformIndices)
3241 {
3242     if (context->getClientMajorVersion() < 3)
3243     {
3244         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3245         return false;
3246     }
3247 
3248     if (uniformCount < 0)
3249     {
3250         context->handleError(InvalidValue());
3251         return false;
3252     }
3253 
3254     Program *programObject = GetValidProgram(context, program);
3255     if (!programObject)
3256     {
3257         return false;
3258     }
3259 
3260     return true;
3261 }
3262 
ValidateGetActiveUniformsiv(Context * context,GLuint program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,GLint * params)3263 bool ValidateGetActiveUniformsiv(Context *context,
3264                                  GLuint program,
3265                                  GLsizei uniformCount,
3266                                  const GLuint *uniformIndices,
3267                                  GLenum pname,
3268                                  GLint *params)
3269 {
3270     if (context->getClientMajorVersion() < 3)
3271     {
3272         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3273         return false;
3274     }
3275 
3276     if (uniformCount < 0)
3277     {
3278         context->handleError(InvalidValue());
3279         return false;
3280     }
3281 
3282     Program *programObject = GetValidProgram(context, program);
3283     if (!programObject)
3284     {
3285         return false;
3286     }
3287 
3288     switch (pname)
3289     {
3290         case GL_UNIFORM_TYPE:
3291         case GL_UNIFORM_SIZE:
3292         case GL_UNIFORM_NAME_LENGTH:
3293         case GL_UNIFORM_BLOCK_INDEX:
3294         case GL_UNIFORM_OFFSET:
3295         case GL_UNIFORM_ARRAY_STRIDE:
3296         case GL_UNIFORM_MATRIX_STRIDE:
3297         case GL_UNIFORM_IS_ROW_MAJOR:
3298             break;
3299 
3300         default:
3301             context->handleError(InvalidEnum());
3302             return false;
3303     }
3304 
3305     if (uniformCount > programObject->getActiveUniformCount())
3306     {
3307         context->handleError(InvalidValue());
3308         return false;
3309     }
3310 
3311     for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3312     {
3313         const GLuint index = uniformIndices[uniformId];
3314 
3315         if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3316         {
3317             context->handleError(InvalidValue());
3318             return false;
3319         }
3320     }
3321 
3322     return true;
3323 }
3324 
ValidateGetUniformBlockIndex(Context * context,GLuint program,const GLchar * uniformBlockName)3325 bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3326 {
3327     if (context->getClientMajorVersion() < 3)
3328     {
3329         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3330         return false;
3331     }
3332 
3333     Program *programObject = GetValidProgram(context, program);
3334     if (!programObject)
3335     {
3336         return false;
3337     }
3338 
3339     return true;
3340 }
3341 
ValidateGetActiveUniformBlockiv(Context * context,GLuint program,GLuint uniformBlockIndex,GLenum pname,GLint * params)3342 bool ValidateGetActiveUniformBlockiv(Context *context,
3343                                      GLuint program,
3344                                      GLuint uniformBlockIndex,
3345                                      GLenum pname,
3346                                      GLint *params)
3347 {
3348     return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3349 }
3350 
ValidateGetActiveUniformBlockName(Context * context,GLuint program,GLuint uniformBlockIndex,GLsizei bufSize,GLsizei * length,GLchar * uniformBlockName)3351 bool ValidateGetActiveUniformBlockName(Context *context,
3352                                        GLuint program,
3353                                        GLuint uniformBlockIndex,
3354                                        GLsizei bufSize,
3355                                        GLsizei *length,
3356                                        GLchar *uniformBlockName)
3357 {
3358     if (context->getClientMajorVersion() < 3)
3359     {
3360         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3361         return false;
3362     }
3363 
3364     Program *programObject = GetValidProgram(context, program);
3365     if (!programObject)
3366     {
3367         return false;
3368     }
3369 
3370     if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3371     {
3372         context->handleError(InvalidValue());
3373         return false;
3374     }
3375 
3376     return true;
3377 }
3378 
ValidateUniformBlockBinding(Context * context,GLuint program,GLuint uniformBlockIndex,GLuint uniformBlockBinding)3379 bool ValidateUniformBlockBinding(Context *context,
3380                                  GLuint program,
3381                                  GLuint uniformBlockIndex,
3382                                  GLuint uniformBlockBinding)
3383 {
3384     if (context->getClientMajorVersion() < 3)
3385     {
3386         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3387         return false;
3388     }
3389 
3390     if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3391     {
3392         context->handleError(InvalidValue());
3393         return false;
3394     }
3395 
3396     Program *programObject = GetValidProgram(context, program);
3397     if (!programObject)
3398     {
3399         return false;
3400     }
3401 
3402     // if never linked, there won't be any uniform blocks
3403     if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3404     {
3405         context->handleError(InvalidValue());
3406         return false;
3407     }
3408 
3409     return true;
3410 }
3411 
ValidateDrawArraysInstanced(Context * context,GLenum mode,GLint first,GLsizei count,GLsizei primcount)3412 bool ValidateDrawArraysInstanced(Context *context,
3413                                  GLenum mode,
3414                                  GLint first,
3415                                  GLsizei count,
3416                                  GLsizei primcount)
3417 {
3418     if (context->getClientMajorVersion() < 3)
3419     {
3420         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3421         return false;
3422     }
3423 
3424     return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3425 }
3426 
ValidateFenceSync(Context * context,GLenum condition,GLbitfield flags)3427 bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3428 {
3429     if (context->getClientMajorVersion() < 3)
3430     {
3431         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3432         return false;
3433     }
3434 
3435     if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3436     {
3437         context->handleError(InvalidEnum());
3438         return false;
3439     }
3440 
3441     if (flags != 0)
3442     {
3443         context->handleError(InvalidValue());
3444         return false;
3445     }
3446 
3447     return true;
3448 }
3449 
ValidateIsSync(Context * context,GLsync sync)3450 bool ValidateIsSync(Context *context, GLsync sync)
3451 {
3452     if (context->getClientMajorVersion() < 3)
3453     {
3454         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3455         return false;
3456     }
3457 
3458     return true;
3459 }
3460 
ValidateDeleteSync(Context * context,GLsync sync)3461 bool ValidateDeleteSync(Context *context, GLsync sync)
3462 {
3463     if (context->getClientMajorVersion() < 3)
3464     {
3465         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3466         return false;
3467     }
3468 
3469     if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
3470     {
3471         context->handleError(InvalidValue());
3472         return false;
3473     }
3474 
3475     return true;
3476 }
3477 
ValidateClientWaitSync(Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)3478 bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3479 {
3480     if (context->getClientMajorVersion() < 3)
3481     {
3482         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3483         return false;
3484     }
3485 
3486     if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3487     {
3488         context->handleError(InvalidValue());
3489         return false;
3490     }
3491 
3492     Sync *clientWaitSync = context->getSync(sync);
3493     if (!clientWaitSync)
3494     {
3495         context->handleError(InvalidValue());
3496         return false;
3497     }
3498 
3499     return true;
3500 }
3501 
ValidateWaitSync(Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)3502 bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3503 {
3504     if (context->getClientMajorVersion() < 3)
3505     {
3506         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3507         return false;
3508     }
3509 
3510     if (flags != 0)
3511     {
3512         context->handleError(InvalidValue());
3513         return false;
3514     }
3515 
3516     if (timeout != GL_TIMEOUT_IGNORED)
3517     {
3518         context->handleError(InvalidValue());
3519         return false;
3520     }
3521 
3522     Sync *waitSync = context->getSync(sync);
3523     if (!waitSync)
3524     {
3525         context->handleError(InvalidValue());
3526         return false;
3527     }
3528 
3529     return true;
3530 }
3531 
ValidateGetInteger64v(Context * context,GLenum pname,GLint64 * params)3532 bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3533 {
3534     if (context->getClientMajorVersion() < 3)
3535     {
3536         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3537         return false;
3538     }
3539 
3540     GLenum nativeType      = GL_NONE;
3541     unsigned int numParams = 0;
3542     if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3543     {
3544         return false;
3545     }
3546 
3547     return true;
3548 }
3549 
ValidateIsSampler(Context * context,GLuint sampler)3550 bool ValidateIsSampler(Context *context, GLuint sampler)
3551 {
3552     if (context->getClientMajorVersion() < 3)
3553     {
3554         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3555         return false;
3556     }
3557 
3558     return true;
3559 }
3560 
ValidateBindSampler(Context * context,GLuint unit,GLuint sampler)3561 bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3562 {
3563     if (context->getClientMajorVersion() < 3)
3564     {
3565         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3566         return false;
3567     }
3568 
3569     if (sampler != 0 && !context->isSampler(sampler))
3570     {
3571         context->handleError(InvalidOperation());
3572         return false;
3573     }
3574 
3575     if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3576     {
3577         context->handleError(InvalidValue());
3578         return false;
3579     }
3580 
3581     return true;
3582 }
3583 
ValidateVertexAttribDivisor(Context * context,GLuint index,GLuint divisor)3584 bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3585 {
3586     if (context->getClientMajorVersion() < 3)
3587     {
3588         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3589         return false;
3590     }
3591 
3592     return ValidateVertexAttribIndex(context, index);
3593 }
3594 
ValidateTexStorage2D(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)3595 bool ValidateTexStorage2D(Context *context,
3596                           GLenum target,
3597                           GLsizei levels,
3598                           GLenum internalformat,
3599                           GLsizei width,
3600                           GLsizei height)
3601 {
3602     if (context->getClientMajorVersion() < 3)
3603     {
3604         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3605         return false;
3606     }
3607 
3608     if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3609                                            1))
3610     {
3611         return false;
3612     }
3613 
3614     return true;
3615 }
3616 
ValidateTexStorage3D(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)3617 bool ValidateTexStorage3D(Context *context,
3618                           GLenum target,
3619                           GLsizei levels,
3620                           GLenum internalformat,
3621                           GLsizei width,
3622                           GLsizei height,
3623                           GLsizei depth)
3624 {
3625     if (context->getClientMajorVersion() < 3)
3626     {
3627         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3628         return false;
3629     }
3630 
3631     if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3632                                            depth))
3633     {
3634         return false;
3635     }
3636 
3637     return true;
3638 }
3639 
ValidateGetBufferParameteri64v(ValidationContext * context,BufferBinding target,GLenum pname,GLint64 * params)3640 bool ValidateGetBufferParameteri64v(ValidationContext *context,
3641                                     BufferBinding target,
3642                                     GLenum pname,
3643                                     GLint64 *params)
3644 {
3645     return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3646 }
3647 
ValidateGetSamplerParameterfv(Context * context,GLuint sampler,GLenum pname,GLfloat * params)3648 bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3649 {
3650     return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3651 }
3652 
ValidateGetSamplerParameteriv(Context * context,GLuint sampler,GLenum pname,GLint * params)3653 bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3654 {
3655     return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3656 }
3657 
ValidateSamplerParameterf(Context * context,GLuint sampler,GLenum pname,GLfloat param)3658 bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3659 {
3660     return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3661 }
3662 
ValidateSamplerParameterfv(Context * context,GLuint sampler,GLenum pname,const GLfloat * params)3663 bool ValidateSamplerParameterfv(Context *context,
3664                                 GLuint sampler,
3665                                 GLenum pname,
3666                                 const GLfloat *params)
3667 {
3668     return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3669 }
3670 
ValidateSamplerParameteri(Context * context,GLuint sampler,GLenum pname,GLint param)3671 bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3672 {
3673     return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
3674 }
3675 
ValidateSamplerParameteriv(Context * context,GLuint sampler,GLenum pname,const GLint * params)3676 bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3677 {
3678     return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3679 }
3680 
ValidateGetVertexAttribIiv(Context * context,GLuint index,GLenum pname,GLint * params)3681 bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3682 {
3683     return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3684 }
3685 
ValidateGetVertexAttribIuiv(Context * context,GLuint index,GLenum pname,GLuint * params)3686 bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3687 {
3688     return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3689 }
3690 
ValidateGetInternalformativ(Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLint * params)3691 bool ValidateGetInternalformativ(Context *context,
3692                                  GLenum target,
3693                                  GLenum internalformat,
3694                                  GLenum pname,
3695                                  GLsizei bufSize,
3696                                  GLint *params)
3697 {
3698     return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3699                                            nullptr);
3700 }
3701 
3702 }  // namespace gl
3703