• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8 
9 #include "libANGLE/validationES3_autogen.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/PixelLocalStorage.h"
19 #include "libANGLE/Renderbuffer.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/VertexArray.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/validationES.h"
24 #include "libANGLE/validationES3.h"
25 
26 using namespace angle;
27 
28 namespace gl
29 {
30 using namespace err;
31 
32 namespace
33 {
ValidateFramebufferTextureMultiviewBaseANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLsizei numViews)34 bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context,
35                                                   angle::EntryPoint entryPoint,
36                                                   GLenum target,
37                                                   GLenum attachment,
38                                                   TextureID texture,
39                                                   GLint level,
40                                                   GLsizei numViews)
41 {
42     if (!(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
43     {
44         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultiviewNotAvailable);
45         return false;
46     }
47 
48     if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
49     {
50         return false;
51     }
52 
53     if (texture.value != 0 && numViews < 1)
54     {
55         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMultiviewViewsTooSmall);
56         return false;
57     }
58 
59     if (static_cast<GLuint>(numViews) > context->getCaps().maxViews)
60     {
61         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMultiviewViewsTooLarge);
62         return false;
63     }
64 
65     return true;
66 }
67 
ValidateFramebufferTextureMultiviewLevelAndFormat(const Context * context,angle::EntryPoint entryPoint,const Texture * texture,GLint level)68 bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context,
69                                                        angle::EntryPoint entryPoint,
70                                                        const Texture *texture,
71                                                        GLint level)
72 {
73     TextureType type = texture->getType();
74     if (!ValidMipLevel(context, type, level))
75     {
76         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
77         return false;
78     }
79 
80     const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
81     if (format.info->compressed)
82     {
83         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
84         return false;
85     }
86     return true;
87 }
88 
ValidateUniformES3(const Context * context,angle::EntryPoint entryPoint,GLenum uniformType,UniformLocation location,GLint count)89 bool ValidateUniformES3(const Context *context,
90                         angle::EntryPoint entryPoint,
91                         GLenum uniformType,
92                         UniformLocation location,
93                         GLint count)
94 {
95     if (context->getClientMajorVersion() < 3)
96     {
97         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
98         return false;
99     }
100 
101     return ValidateUniform(context, entryPoint, uniformType, location, count);
102 }
103 
ValidateUniformMatrixES3(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)104 bool ValidateUniformMatrixES3(const Context *context,
105                               angle::EntryPoint entryPoint,
106                               GLenum valueType,
107                               UniformLocation location,
108                               GLsizei count,
109                               GLboolean transpose)
110 {
111     // Check for ES3 uniform entry points
112     if (context->getClientMajorVersion() < 3)
113     {
114         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
115         return false;
116     }
117 
118     return ValidateUniformMatrix(context, entryPoint, valueType, location, count, transpose);
119 }
120 
ValidateGenOrDeleteES3(const Context * context,angle::EntryPoint entryPoint,GLint n)121 bool ValidateGenOrDeleteES3(const Context *context, angle::EntryPoint entryPoint, GLint n)
122 {
123     if (context->getClientMajorVersion() < 3)
124     {
125         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
126         return false;
127     }
128     return ValidateGenOrDelete(context, entryPoint, n);
129 }
130 
ValidateGenOrDeleteCountES3(const Context * context,angle::EntryPoint entryPoint,GLint count)131 bool ValidateGenOrDeleteCountES3(const Context *context, angle::EntryPoint entryPoint, GLint count)
132 {
133     if (context->getClientMajorVersion() < 3)
134     {
135         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
136         return false;
137     }
138     if (count < 0)
139     {
140         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
141         return false;
142     }
143     return true;
144 }
145 
ValidateCopyTexture3DCommon(const Context * context,angle::EntryPoint entryPoint,const Texture * source,GLint sourceLevel,GLint srcInternalFormat,const Texture * dest,GLint destLevel,GLint internalFormat,TextureTarget destTarget)146 bool ValidateCopyTexture3DCommon(const Context *context,
147                                  angle::EntryPoint entryPoint,
148                                  const Texture *source,
149                                  GLint sourceLevel,
150                                  GLint srcInternalFormat,
151                                  const Texture *dest,
152                                  GLint destLevel,
153                                  GLint internalFormat,
154                                  TextureTarget destTarget)
155 {
156     if (context->getClientMajorVersion() < 3)
157     {
158         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
159         return false;
160     }
161 
162     if (!context->getExtensions().copyTexture3dANGLE)
163     {
164         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable);
165         return false;
166     }
167 
168     if (!ValidTexture3DTarget(context, source->getType()))
169     {
170         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
171         return false;
172     }
173 
174     // Table 1.1 from the ANGLE_copy_texture_3d spec
175     switch (GetUnsizedFormat(srcInternalFormat))
176     {
177         case GL_ALPHA:
178         case GL_LUMINANCE:
179         case GL_LUMINANCE_ALPHA:
180         case GL_RED:
181         case GL_RED_INTEGER:
182         case GL_RG:
183         case GL_RG_INTEGER:
184         case GL_RGB:
185         case GL_RGB_INTEGER:
186         case GL_RGBA:
187         case GL_RGBA_INTEGER:
188         case GL_DEPTH_COMPONENT:
189         case GL_DEPTH_STENCIL:
190             break;
191         default:
192             ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat,
193                                     srcInternalFormat);
194             return false;
195     }
196 
197     if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
198     {
199         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
200         return false;
201     }
202 
203     // Table 1.0 from the ANGLE_copy_texture_3d spec
204     switch (internalFormat)
205     {
206         case GL_RGB:
207         case GL_RGBA:
208         case GL_LUMINANCE:
209         case GL_LUMINANCE_ALPHA:
210         case GL_ALPHA:
211         case GL_R8:
212         case GL_R8_SNORM:
213         case GL_R16F:
214         case GL_R32F:
215         case GL_R8UI:
216         case GL_R8I:
217         case GL_R16UI:
218         case GL_R16I:
219         case GL_R32UI:
220         case GL_R32I:
221         case GL_RG:
222         case GL_RG8:
223         case GL_RG8_SNORM:
224         case GL_RG16F:
225         case GL_RG32F:
226         case GL_RG8UI:
227         case GL_RG8I:
228         case GL_RG16UI:
229         case GL_RG16I:
230         case GL_RG32UI:
231         case GL_RG32I:
232         case GL_RGB8:
233         case GL_RGBX8_ANGLE:
234         case GL_SRGB8:
235         case GL_RGB565:
236         case GL_RGB8_SNORM:
237         case GL_R11F_G11F_B10F:
238         case GL_RGB9_E5:
239         case GL_RGB16F:
240         case GL_RGB32F:
241         case GL_RGB8UI:
242         case GL_RGB8I:
243         case GL_RGB16UI:
244         case GL_RGB16I:
245         case GL_RGB32UI:
246         case GL_RGB32I:
247         case GL_RGBA8:
248         case GL_SRGB8_ALPHA8:
249         case GL_RGBA8_SNORM:
250         case GL_RGB5_A1:
251         case GL_RGBA4:
252         case GL_RGB10_A2:
253         case GL_RGBA16F:
254         case GL_RGBA32F:
255         case GL_RGBA8UI:
256         case GL_RGBA8I:
257         case GL_RGB10_A2UI:
258         case GL_RGBA16UI:
259         case GL_RGBA16I:
260         case GL_RGBA32I:
261         case GL_RGBA32UI:
262             break;
263         default:
264             ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
265             return false;
266     }
267 
268     return true;
269 }
270 
ValidateColorMaskForSharedExponentColorBuffer(const Context * context,angle::EntryPoint entryPoint,GLint drawbuffer)271 bool ValidateColorMaskForSharedExponentColorBuffer(const Context *context,
272                                                    angle::EntryPoint entryPoint,
273                                                    GLint drawbuffer)
274 {
275     const State &state                      = context->getState();
276     const FramebufferAttachment *attachment = state.getDrawFramebuffer()->getDrawBuffer(drawbuffer);
277     if (attachment && attachment->getFormat().info->internalFormat == GL_RGB9_E5)
278     {
279         bool r, g, b, a;
280         state.getBlendStateExt().getColorMaskIndexed(drawbuffer, &r, &g, &b, &a);
281         if (r != g || g != b)
282         {
283             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
284                                    kUnsupportedColorMaskForSharedExponentColorBuffer);
285             return false;
286         }
287     }
288 
289     return true;
290 }
291 }  // anonymous namespace
292 
ValidateTexImageFormatCombination(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum internalFormat,GLenum format,GLenum type)293 static bool ValidateTexImageFormatCombination(const Context *context,
294                                               angle::EntryPoint entryPoint,
295                                               TextureType target,
296                                               GLenum internalFormat,
297                                               GLenum format,
298                                               GLenum type)
299 {
300     // Different validation if on desktop api
301     if (context->getClientType() == EGL_OPENGL_API)
302     {
303         // The type and format are valid if any supported internal format has that type and format
304         if (!ValidDesktopFormat(format))
305         {
306             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
307             return false;
308         }
309 
310         if (!ValidDesktopType(type))
311         {
312             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
313             return false;
314         }
315     }
316     else
317     {
318         // The type and format are valid if any supported internal format has that type and format.
319         // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
320         if (gl::IsYuvFormat(format))
321         {
322             if (!context->getExtensions().yuvInternalFormatANGLE)
323             {
324                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
325                 return false;
326             }
327         }
328         else
329         {
330             if (!ValidES3Format(format))
331             {
332                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
333                 return false;
334             }
335         }
336 
337         if (!ValidES3Type(type) || (type == GL_HALF_FLOAT_OES && context->isWebGL()))
338         {
339             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
340             return false;
341         }
342     }
343 
344     // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
345     // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
346     // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
347     // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
348     if (!ValidES3InternalFormat(internalFormat))
349     {
350         ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kInvalidInternalFormat, internalFormat);
351         return false;
352     }
353 
354     // From the ES 3.0 spec section 3.8.3:
355     // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
356     // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
357     // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
358     // INVALID_OPERATION error.
359     if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
360     {
361         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, k3DDepthStencil);
362         return false;
363     }
364 
365     if (context->getClientType() == EGL_OPENGL_API)
366     {
367         // Check if this is a valid format combination to load texture data
368         if (!ValidDesktopFormatCombination(format, type, internalFormat))
369         {
370             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
371             return false;
372         }
373     }
374     else
375     {
376         // Check if this is a valid format combination to load texture data
377         // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
378         if (gl::IsYuvFormat(format))
379         {
380             if (type != GL_UNSIGNED_BYTE)
381             {
382                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
383                 return false;
384             }
385         }
386         else
387         {
388             if (!ValidES3FormatCombination(format, type, internalFormat))
389             {
390                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
391                 return false;
392             }
393         }
394     }
395 
396     const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat, type);
397     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
398     {
399         ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
400         return false;
401     }
402 
403     return true;
404 }
405 
ValidateES3CompressedFormatForTexture2DArray(const Context * context,angle::EntryPoint entryPoint,GLenum format)406 static bool ValidateES3CompressedFormatForTexture2DArray(const Context *context,
407                                                          angle::EntryPoint entryPoint,
408                                                          GLenum format)
409 {
410     if (IsETC1Format(format) || IsPVRTC1Format(format))
411     {
412         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2D);
413         return false;
414     }
415 
416     return true;
417 }
418 
ValidateES3CompressedFormatForTexture3D(const Context * context,angle::EntryPoint entryPoint,GLenum format)419 static bool ValidateES3CompressedFormatForTexture3D(const Context *context,
420                                                     angle::EntryPoint entryPoint,
421                                                     GLenum format)
422 {
423     if (IsETC1Format(format) || IsPVRTC1Format(format))
424     {
425         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2D);
426         return false;
427     }
428 
429     if (IsETC2EACFormat(format))
430     {
431         // ES 3.1, Section 8.7, page 169.
432         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArray);
433         return false;
434     }
435 
436     if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionAstcHdrKHR ||
437                                     context->getExtensions().textureCompressionAstcSliced3dKHR))
438     {
439         // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
440         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayASTC);
441         return false;
442     }
443 
444     if (IsS3TCFormat(format))
445     {
446         // GL_EXT_texture_compression_s3tc
447         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayS3TC);
448         return false;
449     }
450 
451     if (IsRGTCFormat(format))
452     {
453         // GL_EXT_texture_compression_rgtc
454         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayRGTC);
455         return false;
456     }
457 
458     if (IsBPTCFormat(format) && (context->getLimitations().noCompressedTexture3D))
459     {
460         // GL_EXT_texture_compression_bptc
461         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayBPTC);
462         return false;
463     }
464 
465     return true;
466 }
467 
ValidateES3TexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget 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)468 bool ValidateES3TexImageParametersBase(const Context *context,
469                                        angle::EntryPoint entryPoint,
470                                        TextureTarget target,
471                                        GLint level,
472                                        GLenum internalformat,
473                                        bool isCompressed,
474                                        bool isSubImage,
475                                        GLint xoffset,
476                                        GLint yoffset,
477                                        GLint zoffset,
478                                        GLsizei width,
479                                        GLsizei height,
480                                        GLsizei depth,
481                                        GLint border,
482                                        GLenum format,
483                                        GLenum type,
484                                        GLsizei imageSize,
485                                        const void *pixels)
486 {
487     TextureType texType = TextureTargetToType(target);
488 
489     if (gl::IsYuvFormat(format))
490     {
491         // According to ANGLE_yuv_internal_format, the texture needs to be an immutable
492         // texture, texture target can only be TEXTURE_2D and there is no mipmap support
493         if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
494         {
495             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
496             return false;
497         }
498 
499         if (target != TextureTarget::_2D)
500         {
501             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
502             return false;
503         }
504 
505         if (level != 0)
506         {
507             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
508             return false;
509         }
510     }
511 
512     // Validate image size
513     if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, depth,
514                                   isSubImage))
515     {
516         // Error already processed.
517         return false;
518     }
519 
520     // Verify zero border
521     if (border != 0)
522     {
523         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
524         return false;
525     }
526 
527     if (xoffset < 0 || yoffset < 0 || zoffset < 0)
528     {
529         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
530         return false;
531     }
532 
533     if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
534         std::numeric_limits<GLsizei>::max() - yoffset < height ||
535         std::numeric_limits<GLsizei>::max() - zoffset < depth)
536     {
537         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
538         return false;
539     }
540 
541     const Caps &caps = context->getCaps();
542 
543     switch (texType)
544     {
545         case TextureType::_2D:
546         case TextureType::External:
547         case TextureType::VideoImage:
548             if (width > (caps.max2DTextureSize >> level) ||
549                 height > (caps.max2DTextureSize >> level))
550             {
551                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
552                 return false;
553             }
554             break;
555 
556         case TextureType::Rectangle:
557             ASSERT(level == 0);
558             if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
559             {
560                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
561                 return false;
562             }
563             if (isCompressed)
564             {
565                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRectangleTextureCompressed);
566                 return false;
567             }
568             break;
569 
570         case TextureType::CubeMap:
571             if (!isSubImage && width != height)
572             {
573                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
574                 return false;
575             }
576 
577             if (width > (caps.maxCubeMapTextureSize >> level))
578             {
579                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
580                 return false;
581             }
582             break;
583 
584         case TextureType::_3D:
585             if (width > (caps.max3DTextureSize >> level) ||
586                 height > (caps.max3DTextureSize >> level) ||
587                 depth > (caps.max3DTextureSize >> level))
588             {
589                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
590                 return false;
591             }
592             break;
593 
594         case TextureType::_2DArray:
595             if (width > (caps.max2DTextureSize >> level) ||
596                 height > (caps.max2DTextureSize >> level) || depth > caps.maxArrayTextureLayers)
597             {
598                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
599                 return false;
600             }
601             break;
602 
603         case TextureType::CubeMapArray:
604             if (!isSubImage && width != height)
605             {
606                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
607                 return false;
608             }
609 
610             if (width > (caps.maxCubeMapTextureSize >> level))
611             {
612                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
613                 return false;
614             }
615 
616             if (width > (caps.max3DTextureSize >> level) ||
617                 height > (caps.max3DTextureSize >> level) ||
618                 depth > (caps.max3DTextureSize >> level))
619             {
620                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
621                 return false;
622             }
623 
624             if (!isSubImage && depth % 6 != 0)
625             {
626                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth);
627                 return false;
628             }
629             break;
630 
631         case TextureType::InvalidEnum:
632             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid);
633             return false;
634         default:
635             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(texType));
636             return false;
637     }
638 
639     Texture *texture = context->getTextureByType(texType);
640     if (!texture)
641     {
642         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
643         return false;
644     }
645 
646     if (texture->getImmutableFormat() && !isSubImage)
647     {
648         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
649         return false;
650     }
651 
652     // Validate texture formats
653     GLenum actualInternalFormat =
654         isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
655     if (isSubImage && actualInternalFormat == GL_NONE)
656     {
657         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMipLevel);
658         return false;
659     }
660 
661     const InternalFormat &actualFormatInfo = isSubImage
662                                                  ? *texture->getFormat(target, level).info
663                                                  : GetInternalFormatInfo(internalformat, type);
664     if (isCompressed)
665     {
666         // compressedTexSubImage does not generate GL_INVALID_ENUM when format is unknown or invalid
667         if (!isSubImage)
668         {
669             if (!actualFormatInfo.compressed && !actualFormatInfo.paletted)
670             {
671                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kCompressedMismatch);
672                 return false;
673             }
674 
675             if (!actualFormatInfo.textureSupport(context->getClientVersion(),
676                                                  context->getExtensions()))
677             {
678                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
679                 return false;
680             }
681         }
682 
683         if (texType == TextureType::_2DArray)
684         {
685             GLenum compressedDataFormat = isSubImage ? format : internalformat;
686             if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
687                                                               compressedDataFormat))
688             {
689                 // Error already generated.
690                 return false;
691             }
692         }
693 
694         if (texType == TextureType::_3D)
695         {
696             GLenum compressedDataFormat = isSubImage ? format : internalformat;
697             if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint, compressedDataFormat))
698             {
699                 // Error already generated.
700                 return false;
701             }
702         }
703 
704         if (isSubImage)
705         {
706             if (!ValidCompressedSubImageSize(
707                     context, actualFormatInfo.internalFormat, xoffset, yoffset, zoffset, width,
708                     height, depth, texture->getWidth(target, level),
709                     texture->getHeight(target, level), texture->getDepth(target, level)))
710             {
711                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
712                 return false;
713             }
714 
715             if (format != actualInternalFormat)
716             {
717                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedFormat);
718                 return false;
719             }
720 
721             // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
722             if (IsETC1Format(actualInternalFormat) &&
723                 !context->getExtensions().compressedETC1RGB8SubTextureEXT)
724             {
725                 ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat,
726                                         internalformat);
727                 return false;
728             }
729         }
730         else
731         {
732             if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height,
733                                           depth))
734             {
735                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
736                 return false;
737             }
738         }
739 
740         // Disallow 3D-only compressed formats from being set on 2D textures
741         if (actualFormatInfo.compressedBlockDepth > 1 && texType != TextureType::_3D)
742         {
743             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
744             return false;
745         }
746     }
747     else
748     {
749         // Compressed formats are not valid internal formats for glTexImage*D
750         if (!isSubImage)
751         {
752             const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(internalformat);
753             if (internalFormatInfo.compressed)
754             {
755                 ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kInvalidInternalFormat, internalformat);
756                 return false;
757             }
758         }
759 
760         if (!ValidateTexImageFormatCombination(context, entryPoint, texType, actualInternalFormat,
761                                                format, type))
762         {
763             return false;
764         }
765     }
766 
767     // Validate sub image parameters
768     if (isSubImage)
769     {
770         if (isCompressed != actualFormatInfo.compressed)
771         {
772             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedMismatch);
773             return false;
774         }
775 
776         // Already validated above
777         ASSERT(xoffset >= 0 && yoffset >= 0 && zoffset >= 0);
778         ASSERT(std::numeric_limits<GLsizei>::max() - xoffset >= width &&
779                std::numeric_limits<GLsizei>::max() - yoffset >= height &&
780                std::numeric_limits<GLsizei>::max() - zoffset >= depth);
781 
782         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
783             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
784             static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
785         {
786             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
787             return false;
788         }
789 
790         if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
791             context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
792         {
793             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
794             return false;
795         }
796     }
797 
798     GLenum sizeCheckFormat = isSubImage ? format : internalformat;
799     if (!ValidImageDataSize(context, entryPoint, texType, width, height, depth, sizeCheckFormat,
800                             type, pixels, imageSize))
801     {
802         return false;
803     }
804 
805     // Check for pixel unpack buffer related API errors
806     Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
807     if (pixelUnpackBuffer != nullptr)
808     {
809         // ...data is not evenly divisible into the number of bytes needed to store in memory a
810         // datum
811         // indicated by type.
812         if (!isCompressed)
813         {
814             size_t offset            = reinterpret_cast<size_t>(pixels);
815             size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
816 
817             if ((offset % dataBytesPerPixel) != 0)
818             {
819                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDataTypeNotAligned);
820                 return false;
821             }
822         }
823 
824         // ...the buffer object's data store is currently mapped but not persistently.
825         if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
826         {
827             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
828             return false;
829         }
830     }
831 
832     if (context->getExtensions().webglCompatibilityANGLE)
833     {
834         // Define:
835         //   DataStoreWidth  = (GL_UNPACK_ROW_LENGTH ? GL_UNPACK_ROW_LENGTH : width)
836         //   DataStoreHeight = (GL_UNPACK_IMAGE_HEIGHT ? GL_UNPACK_IMAGE_HEIGHT : height)
837         //
838         // WebGL 2.0 imposes the following additional constraints:
839         //
840         // 1) texImage2D and texSubImage2D generate INVALID_OPERATION if:
841         //      GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
842         //    except for texImage2D if no GL_PIXEL_UNPACK_BUFFER is
843         //    bound and _pixels_ is null.
844         //
845         // 2) texImage3D and texSubImage3D generate INVALID_OPERATION if:
846         //      GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
847         //      GL_UNPACK_SKIP_ROWS + height > DataStoreHeight
848         //    except for texImage3D if no GL_PIXEL_UNPACK_BUFFER is
849         //    bound and _pixels_ is null.
850         if (!pixelUnpackBuffer && !pixels && !isSubImage)
851         {
852             // Exception case for texImage2D or texImage3D, above.
853         }
854         else
855         {
856             const auto &unpack   = context->getState().getUnpackState();
857             GLint dataStoreWidth = unpack.rowLength ? unpack.rowLength : width;
858             if (unpack.skipPixels + width > dataStoreWidth)
859             {
860                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUnpackParametersForWebGL);
861                 return false;
862             }
863             if (target == TextureTarget::_3D || target == TextureTarget::_2DArray)
864             {
865                 GLint dataStoreHeight = unpack.imageHeight ? unpack.imageHeight : height;
866                 if (unpack.skipRows + height > dataStoreHeight)
867                 {
868                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUnpackParametersForWebGL);
869                     return false;
870                 }
871             }
872         }
873     }
874 
875     return true;
876 }
877 
ValidateES3TexImage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget 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)878 bool ValidateES3TexImage2DParameters(const Context *context,
879                                      angle::EntryPoint entryPoint,
880                                      TextureTarget target,
881                                      GLint level,
882                                      GLenum internalformat,
883                                      bool isCompressed,
884                                      bool isSubImage,
885                                      GLint xoffset,
886                                      GLint yoffset,
887                                      GLint zoffset,
888                                      GLsizei width,
889                                      GLsizei height,
890                                      GLsizei depth,
891                                      GLint border,
892                                      GLenum format,
893                                      GLenum type,
894                                      GLsizei imageSize,
895                                      const void *pixels)
896 {
897     if (!ValidTexture2DDestinationTarget(context, target))
898     {
899         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
900         return false;
901     }
902 
903     return ValidateES3TexImageParametersBase(
904         context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
905         yoffset, zoffset, width, height, depth, border, format, type, imageSize, pixels);
906 }
907 
ValidateES3TexImage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget 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)908 bool ValidateES3TexImage3DParameters(const Context *context,
909                                      angle::EntryPoint entryPoint,
910                                      TextureTarget target,
911                                      GLint level,
912                                      GLenum internalformat,
913                                      bool isCompressed,
914                                      bool isSubImage,
915                                      GLint xoffset,
916                                      GLint yoffset,
917                                      GLint zoffset,
918                                      GLsizei width,
919                                      GLsizei height,
920                                      GLsizei depth,
921                                      GLint border,
922                                      GLenum format,
923                                      GLenum type,
924                                      GLsizei bufSize,
925                                      const void *pixels)
926 {
927     if (!ValidTexture3DDestinationTarget(context, target))
928     {
929         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
930         return false;
931     }
932 
933     return ValidateES3TexImageParametersBase(
934         context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
935         yoffset, zoffset, width, height, depth, border, format, type, bufSize, pixels);
936 }
937 
938 struct EffectiveInternalFormatInfo
939 {
940     GLenum effectiveFormat;
941     GLenum destFormat;
942     GLuint minRedBits;
943     GLuint maxRedBits;
944     GLuint minGreenBits;
945     GLuint maxGreenBits;
946     GLuint minBlueBits;
947     GLuint maxBlueBits;
948     GLuint minAlphaBits;
949     GLuint maxAlphaBits;
950 };
951 
QueryEffectiveFormatList(const InternalFormat & srcFormat,GLenum targetFormat,const EffectiveInternalFormatInfo * list,size_t size,GLenum * outEffectiveFormat)952 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
953                                      GLenum targetFormat,
954                                      const EffectiveInternalFormatInfo *list,
955                                      size_t size,
956                                      GLenum *outEffectiveFormat)
957 {
958     for (size_t curFormat = 0; curFormat < size; ++curFormat)
959     {
960         const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
961         if ((formatInfo.destFormat == targetFormat) &&
962             (formatInfo.minRedBits <= srcFormat.redBits &&
963              formatInfo.maxRedBits >= srcFormat.redBits) &&
964             (formatInfo.minGreenBits <= srcFormat.greenBits &&
965              formatInfo.maxGreenBits >= srcFormat.greenBits) &&
966             (formatInfo.minBlueBits <= srcFormat.blueBits &&
967              formatInfo.maxBlueBits >= srcFormat.blueBits) &&
968             (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
969              formatInfo.maxAlphaBits >= srcFormat.alphaBits))
970         {
971             *outEffectiveFormat = formatInfo.effectiveFormat;
972             return true;
973         }
974     }
975 
976     *outEffectiveFormat = GL_NONE;
977     return false;
978 }
979 
GetSizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,GLenum * outEffectiveFormat)980 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
981                                          GLenum *outEffectiveFormat)
982 {
983     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
984     // Effective internal format coresponding to destination internal format and linear source
985     // buffer component sizes.
986     //                                       | Source channel min/max sizes |
987     //   Effective Internal Format   |  N/A  |  R   |  G   |  B   |  A      |
988     // clang-format off
989     constexpr EffectiveInternalFormatInfo list[] = {
990         { GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8 },
991         { GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0 },
992         { GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0 },
993         { GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0 },
994         { GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0 },
995         { GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4 },
996         { GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1 },
997         { GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8 },
998         { GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
999     };
1000     // clang-format on
1001 
1002     return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
1003 }
1004 
GetUnsizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)1005 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
1006                                            const InternalFormat &destFormat,
1007                                            GLenum *outEffectiveFormat)
1008 {
1009     constexpr GLuint umax = UINT_MAX;
1010 
1011     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
1012     // Effective internal format coresponding to destination internal format andlinear source buffer
1013     // component sizes.
1014     //                                                   |   Source channel min/max sizes   |
1015     //     Effective Internal Format |   Dest Format     |   R   |    G   |    B   |    A   |
1016     // clang-format off
1017     constexpr EffectiveInternalFormatInfo list[] = {
1018         { GL_ALPHA8_EXT,             GL_ALPHA,           0, umax, 0, umax, 0, umax, 1,    8 },
1019         { GL_LUMINANCE8_EXT,         GL_LUMINANCE,       1,    8, 0, umax, 0, umax, 0, umax },
1020         { GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, 1,    8, 0, umax, 0, umax, 1,    8 },
1021         { GL_RGB565,                 GL_RGB,             1,    5, 1,    6, 1,    5, 0, umax },
1022         { GL_RGB8,                   GL_RGB,             6,    8, 7,    8, 6,    8, 0, umax },
1023         { GL_RGBA4,                  GL_RGBA,            1,    4, 1,    4, 1,    4, 1,    4 },
1024         { GL_RGB5_A1,                GL_RGBA,            5,    5, 5,    5, 5,    5, 1,    1 },
1025         { GL_RGBA8,                  GL_RGBA,            5,    8, 5,    8, 5,    8, 5,    8 },
1026     };
1027     // clang-format on
1028 
1029     return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
1030                                     outEffectiveFormat);
1031 }
1032 
GetEffectiveInternalFormat(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)1033 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
1034                                        const InternalFormat &destFormat,
1035                                        GLenum *outEffectiveFormat)
1036 {
1037     if (destFormat.sized)
1038     {
1039         return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
1040     }
1041     else
1042     {
1043         return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
1044     }
1045 }
1046 
EqualOrFirstZero(GLuint first,GLuint second)1047 static bool EqualOrFirstZero(GLuint first, GLuint second)
1048 {
1049     return first == 0 || first == second;
1050 }
1051 
IsValidES3CopyTexImageCombination(const InternalFormat & textureFormatInfo,const InternalFormat & framebufferFormatInfo,FramebufferID readBufferHandle)1052 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
1053                                               const InternalFormat &framebufferFormatInfo,
1054                                               FramebufferID readBufferHandle)
1055 {
1056     if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
1057     {
1058         return false;
1059     }
1060 
1061     // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
1062     // must both be signed, unsigned, or fixed point and both source and destinations
1063     // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
1064     // conversion between fixed and floating point.
1065 
1066     if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
1067         (framebufferFormatInfo.colorEncoding == GL_SRGB))
1068     {
1069         return false;
1070     }
1071 
1072     if (((textureFormatInfo.componentType == GL_INT) !=
1073          (framebufferFormatInfo.componentType == GL_INT)) ||
1074         ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
1075          (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
1076     {
1077         return false;
1078     }
1079 
1080     if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
1081          textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
1082         !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
1083           framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
1084     {
1085         return false;
1086     }
1087 
1088     if ((textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) !=
1089         (framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
1090     {
1091         return false;
1092     }
1093 
1094     // Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that
1095     // the KHR dEQP tests enforce:
1096     //
1097     // Note that the above rules disallow matches where some components sizes are smaller and
1098     // others are larger (such as RGB10_A2).
1099     if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
1100     {
1101         return false;
1102     }
1103 
1104     // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
1105     // The effective internal format of the source buffer is determined with the following rules
1106     // applied in order:
1107     //    * If the source buffer is a texture or renderbuffer that was created with a sized internal
1108     //      format then the effective internal format is the source buffer's sized internal format.
1109     //    * If the source buffer is a texture that was created with an unsized base internal format,
1110     //      then the effective internal format is the source image array's effective internal
1111     //      format, as specified by table 3.12, which is determined from the <format> and <type>
1112     //      that were used when the source image array was specified by TexImage*.
1113     //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
1114     //      where Destination Internal Format matches internalformat and where the [source channel
1115     //      sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
1116     //      is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
1117     //      FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
1118     const InternalFormat *sourceEffectiveFormat = nullptr;
1119     if (readBufferHandle.value != 0)
1120     {
1121         // Not the default framebuffer, therefore the read buffer must be a user-created texture or
1122         // renderbuffer
1123         if (framebufferFormatInfo.sized)
1124         {
1125             sourceEffectiveFormat = &framebufferFormatInfo;
1126         }
1127         else
1128         {
1129             // Renderbuffers cannot be created with an unsized internal format, so this must be an
1130             // unsized-format texture. We can use the same table we use when creating textures to
1131             // get its effective sized format.
1132             sourceEffectiveFormat =
1133                 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
1134         }
1135     }
1136     else
1137     {
1138         // The effective internal format must be derived from the source framebuffer's channel
1139         // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
1140         if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
1141         {
1142             GLenum effectiveFormat;
1143             if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
1144                                            &effectiveFormat))
1145             {
1146                 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
1147             }
1148             else
1149             {
1150                 return false;
1151             }
1152         }
1153         else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
1154         {
1155             // SRGB buffers can only be copied to sized format destinations according to table 3.18
1156             if (textureFormatInfo.sized &&
1157                 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
1158                 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
1159                 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
1160                 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
1161             {
1162                 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
1163             }
1164             else
1165             {
1166                 return false;
1167             }
1168         }
1169         else
1170         {
1171             UNREACHABLE();
1172             return false;
1173         }
1174     }
1175 
1176     if (textureFormatInfo.sized)
1177     {
1178         // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
1179         // sized, component sizes of the source and destination formats must exactly match if the
1180         // destination format exists.
1181         if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
1182             !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
1183             !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
1184             !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
1185         {
1186             return false;
1187         }
1188     }
1189 
1190     return true;  // A conversion function exists, and no rule in the specification has precluded
1191                   // conversion between these formats.
1192 }
1193 
ValidateES3CopyTexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1194 bool ValidateES3CopyTexImageParametersBase(const Context *context,
1195                                            angle::EntryPoint entryPoint,
1196                                            TextureTarget target,
1197                                            GLint level,
1198                                            GLenum internalformat,
1199                                            bool isSubImage,
1200                                            GLint xoffset,
1201                                            GLint yoffset,
1202                                            GLint zoffset,
1203                                            GLint x,
1204                                            GLint y,
1205                                            GLsizei width,
1206                                            GLsizei height,
1207                                            GLint border)
1208 {
1209     Format textureFormat = Format::Invalid();
1210     if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1211                                             isSubImage, xoffset, yoffset, zoffset, x, y, width,
1212                                             height, border, &textureFormat))
1213     {
1214         return false;
1215     }
1216     ASSERT(textureFormat.valid() || !isSubImage);
1217 
1218     const auto &state               = context->getState();
1219     Framebuffer *framebuffer        = state.getReadFramebuffer();
1220     FramebufferID readFramebufferID = framebuffer->id();
1221 
1222     if (!ValidateFramebufferComplete(context, entryPoint, framebuffer))
1223     {
1224         return false;
1225     }
1226 
1227     // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
1228     // resolved before copying
1229     if (!framebuffer->isDefault() &&
1230         !ValidateFramebufferNotMultisampled(context, entryPoint, framebuffer, true))
1231     {
1232         return false;
1233     }
1234 
1235     const FramebufferAttachment *source = framebuffer->getReadColorAttachment();
1236 
1237     // According to ES 3.x spec, if the internalformat of the texture
1238     // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
1239     if (textureFormat.info->internalFormat == GL_RGB9_E5)
1240     {
1241         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
1242         return false;
1243     }
1244 
1245     if (isSubImage)
1246     {
1247         if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
1248                                                readFramebufferID))
1249         {
1250             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCopyCombination);
1251             return false;
1252         }
1253     }
1254     else
1255     {
1256         // Use format/type from the source FBO. (Might not be perfect for all cases?)
1257         const InternalFormat &framebufferFormat = *source->getFormat().info;
1258         const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
1259         if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
1260         {
1261             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCopyCombination);
1262             return false;
1263         }
1264     }
1265 
1266     // If width or height is zero, it is a no-op.  Return false without setting an error.
1267     return (width > 0 && height > 0);
1268 }
1269 
ValidateES3CopyTexImage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1270 bool ValidateES3CopyTexImage2DParameters(const Context *context,
1271                                          angle::EntryPoint entryPoint,
1272                                          TextureTarget target,
1273                                          GLint level,
1274                                          GLenum internalformat,
1275                                          bool isSubImage,
1276                                          GLint xoffset,
1277                                          GLint yoffset,
1278                                          GLint zoffset,
1279                                          GLint x,
1280                                          GLint y,
1281                                          GLsizei width,
1282                                          GLsizei height,
1283                                          GLint border)
1284 {
1285     if (!ValidTexture2DDestinationTarget(context, target))
1286     {
1287         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1288         return false;
1289     }
1290 
1291     return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1292                                                  isSubImage, xoffset, yoffset, zoffset, x, y, width,
1293                                                  height, border);
1294 }
1295 
ValidateES3CopyTexImage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1296 bool ValidateES3CopyTexImage3DParameters(const Context *context,
1297                                          angle::EntryPoint entryPoint,
1298                                          TextureTarget target,
1299                                          GLint level,
1300                                          GLenum internalformat,
1301                                          bool isSubImage,
1302                                          GLint xoffset,
1303                                          GLint yoffset,
1304                                          GLint zoffset,
1305                                          GLint x,
1306                                          GLint y,
1307                                          GLsizei width,
1308                                          GLsizei height,
1309                                          GLint border)
1310 {
1311     if (!ValidTexture3DDestinationTarget(context, target))
1312     {
1313         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1314         return false;
1315     }
1316 
1317     return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1318                                                  isSubImage, xoffset, yoffset, zoffset, x, y, width,
1319                                                  height, border);
1320 }
1321 
ValidateES3TexStorageParametersLevel(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth)1322 bool ValidateES3TexStorageParametersLevel(const Context *context,
1323                                           angle::EntryPoint entryPoint,
1324                                           TextureType target,
1325                                           GLsizei levels,
1326                                           GLsizei width,
1327                                           GLsizei height,
1328                                           GLsizei depth)
1329 {
1330     GLsizei maxDim = std::max(width, height);
1331     if (target != TextureType::_2DArray)
1332     {
1333         maxDim = std::max(maxDim, depth);
1334     }
1335 
1336     if (levels > log2(maxDim) + 1)
1337     {
1338         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMipLevels);
1339         return false;
1340     }
1341 
1342     return true;
1343 }
1344 
ValidateES3TexStorageParametersExtent(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth)1345 bool ValidateES3TexStorageParametersExtent(const Context *context,
1346                                            angle::EntryPoint entryPoint,
1347                                            TextureType target,
1348                                            GLsizei levels,
1349                                            GLsizei width,
1350                                            GLsizei height,
1351                                            GLsizei depth)
1352 {
1353     const Caps &caps = context->getCaps();
1354 
1355     switch (target)
1356     {
1357         case TextureType::_2D:
1358         {
1359             if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1360             {
1361                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1362                 return false;
1363             }
1364         }
1365         break;
1366 
1367         case TextureType::Rectangle:
1368         {
1369             if (levels != 1)
1370             {
1371                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevels);
1372                 return false;
1373             }
1374 
1375             if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1376             {
1377                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1378                 return false;
1379             }
1380         }
1381         break;
1382 
1383         case TextureType::CubeMap:
1384         {
1385             if (width != height)
1386             {
1387                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1388                 return false;
1389             }
1390 
1391             if (width > caps.maxCubeMapTextureSize)
1392             {
1393                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1394                 return false;
1395             }
1396         }
1397         break;
1398 
1399         case TextureType::_3D:
1400         {
1401             if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
1402                 depth > caps.max3DTextureSize)
1403             {
1404                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1405                 return false;
1406             }
1407         }
1408         break;
1409 
1410         case TextureType::_2DArray:
1411         {
1412             if (width > caps.max2DTextureSize || height > caps.max2DTextureSize ||
1413                 depth > caps.maxArrayTextureLayers)
1414             {
1415                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1416                 return false;
1417             }
1418         }
1419         break;
1420 
1421         case TextureType::CubeMapArray:
1422         {
1423             if (width != height)
1424             {
1425                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1426                 return false;
1427             }
1428 
1429             if (width > caps.maxCubeMapTextureSize)
1430             {
1431                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1432                 return false;
1433             }
1434 
1435             if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
1436                 depth > caps.max3DTextureSize)
1437             {
1438                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1439                 return false;
1440             }
1441 
1442             if (depth % 6 != 0)
1443             {
1444                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth);
1445                 return false;
1446             }
1447         }
1448         break;
1449 
1450         default:
1451             UNREACHABLE();
1452             return false;
1453     }
1454 
1455     return true;
1456 }
1457 
ValidateES3TexStorageParametersTexObject(const Context * context,angle::EntryPoint entryPoint,TextureType target)1458 bool ValidateES3TexStorageParametersTexObject(const Context *context,
1459                                               angle::EntryPoint entryPoint,
1460                                               TextureType target)
1461 {
1462     Texture *texture = context->getTextureByType(target);
1463     if (!texture || texture->id().value == 0)
1464     {
1465         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
1466         return false;
1467     }
1468 
1469     if (texture->getImmutableFormat())
1470     {
1471         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
1472         return false;
1473     }
1474 
1475     return true;
1476 }
1477 
ValidateES3TexStorageParametersFormat(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1478 bool ValidateES3TexStorageParametersFormat(const Context *context,
1479                                            angle::EntryPoint entryPoint,
1480                                            TextureType target,
1481                                            GLsizei levels,
1482                                            GLenum internalformat,
1483                                            GLsizei width,
1484                                            GLsizei height,
1485                                            GLsizei depth)
1486 {
1487     // From ANGLE_texture_external_yuv_sampling:
1488     // Texture target can only be TEXTURE_2D, there is no mipmap support
1489     if (gl::IsYuvFormat(internalformat))
1490     {
1491         if (!context->getExtensions().yuvInternalFormatANGLE)
1492         {
1493             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1494             return false;
1495         }
1496 
1497         if (target != TextureType::_2D)
1498         {
1499             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1500             return false;
1501         }
1502 
1503         if (levels != 1)
1504         {
1505             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
1506             return false;
1507         }
1508     }
1509 
1510     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1511     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1512     {
1513         ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1514         return false;
1515     }
1516 
1517     if (!formatInfo.sized)
1518     {
1519         ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1520         return false;
1521     }
1522 
1523     if (formatInfo.compressed)
1524     {
1525         if (target == TextureType::Rectangle)
1526         {
1527             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRectangleTextureCompressed);
1528             return false;
1529         }
1530 
1531         if (target == TextureType::_2DArray)
1532         {
1533             if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
1534                                                               formatInfo.internalFormat))
1535             {
1536                 // Error already generated.
1537                 return false;
1538             }
1539         }
1540 
1541         if (target == TextureType::_3D)
1542         {
1543             if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint,
1544                                                          formatInfo.internalFormat))
1545             {
1546                 // Error already generated.
1547                 return false;
1548             }
1549         }
1550 
1551         if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
1552         {
1553             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1554             return false;
1555         }
1556     }
1557 
1558     return true;
1559 }
1560 
ValidateES3TexStorageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1561 bool ValidateES3TexStorageParametersBase(const Context *context,
1562                                          angle::EntryPoint entryPoint,
1563                                          TextureType target,
1564                                          GLsizei levels,
1565                                          GLenum internalformat,
1566                                          GLsizei width,
1567                                          GLsizei height,
1568                                          GLsizei depth)
1569 {
1570     if (width < 1 || height < 1 || depth < 1 || levels < 1)
1571     {
1572         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
1573         return false;
1574     }
1575 
1576     if (!ValidateES3TexStorageParametersLevel(context, entryPoint, target, levels, width, height,
1577                                               depth))
1578     {
1579         // Error already generated.
1580         return false;
1581     }
1582 
1583     if (!ValidateES3TexStorageParametersExtent(context, entryPoint, target, levels, width, height,
1584                                                depth))
1585     {
1586         // Error already generated.
1587         return false;
1588     }
1589 
1590     if (!ValidateES3TexStorageParametersTexObject(context, entryPoint, target))
1591     {
1592         // Error already generated.
1593         return false;
1594     }
1595 
1596     if (!ValidateES3TexStorageParametersFormat(context, entryPoint, target, levels, internalformat,
1597                                                width, height, depth))
1598     {
1599         // Error already generated.
1600         return false;
1601     }
1602 
1603     return true;
1604 }
1605 
ValidateES3TexStorage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1606 bool ValidateES3TexStorage2DParameters(const Context *context,
1607                                        angle::EntryPoint entryPoint,
1608                                        TextureType target,
1609                                        GLsizei levels,
1610                                        GLenum internalformat,
1611                                        GLsizei width,
1612                                        GLsizei height,
1613                                        GLsizei depth)
1614 {
1615     if (!ValidTexture2DTarget(context, target))
1616     {
1617         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1618         return false;
1619     }
1620 
1621     return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
1622                                                width, height, depth);
1623 }
1624 
ValidateES3TexStorage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1625 bool ValidateES3TexStorage3DParameters(const Context *context,
1626                                        angle::EntryPoint entryPoint,
1627                                        TextureType target,
1628                                        GLsizei levels,
1629                                        GLenum internalformat,
1630                                        GLsizei width,
1631                                        GLsizei height,
1632                                        GLsizei depth)
1633 {
1634     if (!ValidTexture3DTarget(context, target))
1635     {
1636         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1637         return false;
1638     }
1639 
1640     return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
1641                                                width, height, depth);
1642 }
1643 
ValidateBeginQuery(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)1644 bool ValidateBeginQuery(const Context *context,
1645                         angle::EntryPoint entryPoint,
1646                         QueryType target,
1647                         QueryID id)
1648 {
1649     if (context->getClientMajorVersion() < 3)
1650     {
1651         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1652         return false;
1653     }
1654 
1655     return ValidateBeginQueryBase(context, entryPoint, target, id);
1656 }
1657 
ValidateEndQuery(const Context * context,angle::EntryPoint entryPoint,QueryType target)1658 bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType target)
1659 {
1660     if (context->getClientMajorVersion() < 3)
1661     {
1662         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1663         return false;
1664     }
1665 
1666     return ValidateEndQueryBase(context, entryPoint, target);
1667 }
1668 
ValidateGetQueryiv(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,const GLint * params)1669 bool ValidateGetQueryiv(const Context *context,
1670                         angle::EntryPoint entryPoint,
1671                         QueryType target,
1672                         GLenum pname,
1673                         const GLint *params)
1674 {
1675     if (context->getClientMajorVersion() < 3)
1676     {
1677         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1678         return false;
1679     }
1680 
1681     return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
1682 }
1683 
ValidateGetQueryObjectuiv(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLuint * params)1684 bool ValidateGetQueryObjectuiv(const Context *context,
1685                                angle::EntryPoint entryPoint,
1686                                QueryID id,
1687                                GLenum pname,
1688                                const GLuint *params)
1689 {
1690     if (context->getClientMajorVersion() < 3)
1691     {
1692         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1693         return false;
1694     }
1695 
1696     return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
1697 }
1698 
ValidateFramebufferTextureLayer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint layer)1699 bool ValidateFramebufferTextureLayer(const Context *context,
1700                                      angle::EntryPoint entryPoint,
1701                                      GLenum target,
1702                                      GLenum attachment,
1703                                      TextureID texture,
1704                                      GLint level,
1705                                      GLint layer)
1706 {
1707     if (context->getClientMajorVersion() < 3)
1708     {
1709         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1710         return false;
1711     }
1712 
1713     if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
1714     {
1715         return false;
1716     }
1717 
1718     const Caps &caps = context->getCaps();
1719     if (texture.value != 0)
1720     {
1721         if (layer < 0)
1722         {
1723             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLayer);
1724             return false;
1725         }
1726 
1727         Texture *tex = context->getTexture(texture);
1728         ASSERT(tex);
1729 
1730         switch (tex->getType())
1731         {
1732             case TextureType::_2DArray:
1733             {
1734                 if (level > log2(caps.max2DTextureSize))
1735                 {
1736                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1737                     return false;
1738                 }
1739 
1740                 if (layer >= caps.maxArrayTextureLayers)
1741                 {
1742                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1743                     return false;
1744                 }
1745             }
1746             break;
1747 
1748             case TextureType::_3D:
1749             {
1750                 if (level > log2(caps.max3DTextureSize))
1751                 {
1752                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1753                     return false;
1754                 }
1755 
1756                 if (layer >= caps.max3DTextureSize)
1757                 {
1758                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1759                     return false;
1760                 }
1761             }
1762             break;
1763 
1764             case TextureType::_2DMultisampleArray:
1765             {
1766                 if (level != 0)
1767                 {
1768                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1769                     return false;
1770                 }
1771 
1772                 if (layer >= caps.maxArrayTextureLayers)
1773                 {
1774                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1775                     return false;
1776                 }
1777             }
1778             break;
1779 
1780             case TextureType::CubeMap:
1781             {
1782                 if (level > log2(caps.maxCubeMapTextureSize))
1783                 {
1784                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1785                     return false;
1786                 }
1787 
1788                 if (layer >= static_cast<GLint>(kCubeFaceCount))
1789                 {
1790                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1791                     return false;
1792                 }
1793             }
1794             break;
1795 
1796             case TextureType::CubeMapArray:
1797             {
1798                 if (level > log2(caps.maxCubeMapTextureSize))
1799                 {
1800                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1801                     return false;
1802                 }
1803 
1804                 if (layer >= caps.maxArrayTextureLayers)
1805                 {
1806                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1807                     return false;
1808                 }
1809             }
1810             break;
1811 
1812             default:
1813                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1814                                        kFramebufferTextureLayerIncorrectTextureType);
1815                 return false;
1816         }
1817 
1818         const auto &format = tex->getFormat(TextureTypeToTarget(tex->getType(), layer), level);
1819         if (format.info->compressed)
1820         {
1821             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
1822             return false;
1823         }
1824     }
1825 
1826     return true;
1827 }
1828 
ValidateInvalidateFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments)1829 bool ValidateInvalidateFramebuffer(const Context *context,
1830                                    angle::EntryPoint entryPoint,
1831                                    GLenum target,
1832                                    GLsizei numAttachments,
1833                                    const GLenum *attachments)
1834 {
1835     if (context->getClientMajorVersion() < 3)
1836     {
1837         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1838         return false;
1839     }
1840 
1841     bool defaultFramebuffer = false;
1842 
1843     switch (target)
1844     {
1845         case GL_DRAW_FRAMEBUFFER:
1846         case GL_FRAMEBUFFER:
1847             defaultFramebuffer = context->getState().getDrawFramebuffer()->isDefault();
1848             break;
1849         case GL_READ_FRAMEBUFFER:
1850             defaultFramebuffer = context->getState().getReadFramebuffer()->isDefault();
1851             break;
1852         default:
1853             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1854             return false;
1855     }
1856 
1857     return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
1858                                           defaultFramebuffer);
1859 }
1860 
ValidateInvalidateSubFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)1861 bool ValidateInvalidateSubFramebuffer(const Context *context,
1862                                       angle::EntryPoint entryPoint,
1863                                       GLenum target,
1864                                       GLsizei numAttachments,
1865                                       const GLenum *attachments,
1866                                       GLint x,
1867                                       GLint y,
1868                                       GLsizei width,
1869                                       GLsizei height)
1870 {
1871     if (width < 0 || height < 0)
1872     {
1873         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
1874         return false;
1875     }
1876 
1877     return ValidateInvalidateFramebuffer(context, entryPoint, target, numAttachments, attachments);
1878 }
1879 
ValidateClearBuffer(const Context * context,angle::EntryPoint entryPoint)1880 bool ValidateClearBuffer(const Context *context, angle::EntryPoint entryPoint)
1881 {
1882     if (context->getClientMajorVersion() < 3)
1883     {
1884         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1885         return false;
1886     }
1887 
1888     if (!ValidateFramebufferComplete(context, entryPoint, context->getState().getDrawFramebuffer()))
1889     {
1890         return false;
1891     }
1892 
1893     return true;
1894 }
1895 
ValidateDrawRangeElements(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,DrawElementsType type,const void * indices)1896 bool ValidateDrawRangeElements(const Context *context,
1897                                angle::EntryPoint entryPoint,
1898                                PrimitiveMode mode,
1899                                GLuint start,
1900                                GLuint end,
1901                                GLsizei count,
1902                                DrawElementsType type,
1903                                const void *indices)
1904 {
1905     if (context->getClientMajorVersion() < 3)
1906     {
1907         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1908         return false;
1909     }
1910 
1911     if (end < start)
1912     {
1913         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidElementRange);
1914         return false;
1915     }
1916 
1917     if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1))
1918     {
1919         return false;
1920     }
1921 
1922     // Skip range checks for no-op calls.
1923     if (count <= 0)
1924     {
1925         return true;
1926     }
1927 
1928     return true;
1929 }
1930 
ValidateGetUniformuiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,const GLuint * params)1931 bool ValidateGetUniformuiv(const Context *context,
1932                            angle::EntryPoint entryPoint,
1933                            ShaderProgramID program,
1934                            UniformLocation location,
1935                            const GLuint *params)
1936 {
1937     if (context->getClientMajorVersion() < 3)
1938     {
1939         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1940         return false;
1941     }
1942 
1943     return ValidateGetUniformBase(context, entryPoint, program, location);
1944 }
1945 
ValidateReadBuffer(const Context * context,angle::EntryPoint entryPoint,GLenum src)1946 bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src)
1947 {
1948     if (context->getClientMajorVersion() < 3)
1949     {
1950         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1951         return false;
1952     }
1953 
1954     const Framebuffer *readFBO = context->getState().getReadFramebuffer();
1955 
1956     if (readFBO == nullptr)
1957     {
1958         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoReadFramebuffer);
1959         return false;
1960     }
1961 
1962     if (src == GL_NONE)
1963     {
1964         return true;
1965     }
1966 
1967     if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
1968     {
1969         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidReadBuffer);
1970         return false;
1971     }
1972 
1973     if (readFBO->isDefault())
1974     {
1975         if (src != GL_BACK)
1976         {
1977             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDefaultReadBuffer);
1978             return false;
1979         }
1980     }
1981     else
1982     {
1983         GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1984 
1985         if (drawBuffer >= static_cast<GLuint>(context->getCaps().maxColorAttachments))
1986         {
1987             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
1988             return false;
1989         }
1990     }
1991 
1992     return true;
1993 }
1994 
ValidateCompressedTexImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)1995 bool ValidateCompressedTexImage3D(const Context *context,
1996                                   angle::EntryPoint entryPoint,
1997                                   TextureTarget target,
1998                                   GLint level,
1999                                   GLenum internalformat,
2000                                   GLsizei width,
2001                                   GLsizei height,
2002                                   GLsizei depth,
2003                                   GLint border,
2004                                   GLsizei imageSize,
2005                                   const void *data)
2006 {
2007     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2008     {
2009         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2010         return false;
2011     }
2012 
2013     if (!ValidTextureTarget(context, TextureTargetToType(target)))
2014     {
2015         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2016         return false;
2017     }
2018 
2019     // Validate image size
2020     if (!ValidImageSizeParameters(context, entryPoint, TextureTargetToType(target), level, width,
2021                                   height, depth, false))
2022     {
2023         // Error already generated.
2024         return false;
2025     }
2026 
2027     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
2028     if (!formatInfo.compressed)
2029     {
2030         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidCompressedFormat);
2031         return false;
2032     }
2033 
2034     GLuint blockSize = 0;
2035     if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
2036     {
2037         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
2038         return false;
2039     }
2040 
2041     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2042     {
2043         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2044         return false;
2045     }
2046 
2047     // 3D texture target validation
2048     if (target != TextureTarget::_3D && target != TextureTarget::_2DArray)
2049     {
2050         if (context->getClientVersion() < ES_3_2 || target != TextureTarget::CubeMapArray)
2051         {
2052             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2053             return false;
2054         }
2055     }
2056 
2057     // validateES3TexImageFormat sets the error code if there is an error
2058     if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat, true,
2059                                          false, 0, 0, 0, width, height, depth, border, GL_NONE,
2060                                          GL_NONE, -1, data))
2061     {
2062         return false;
2063     }
2064 
2065     return true;
2066 }
2067 
ValidateCompressedTexImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)2068 bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
2069                                              angle::EntryPoint entryPoint,
2070                                              TextureTarget target,
2071                                              GLint level,
2072                                              GLenum internalformat,
2073                                              GLsizei width,
2074                                              GLsizei height,
2075                                              GLsizei depth,
2076                                              GLint border,
2077                                              GLsizei imageSize,
2078                                              GLsizei dataSize,
2079                                              const void *data)
2080 {
2081     if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
2082     {
2083         return false;
2084     }
2085 
2086     return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
2087                                         height, depth, border, imageSize, data);
2088 }
2089 
ValidateBindVertexArray(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)2090 bool ValidateBindVertexArray(const Context *context,
2091                              angle::EntryPoint entryPoint,
2092                              VertexArrayID array)
2093 {
2094     if (context->getClientMajorVersion() < 3)
2095     {
2096         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2097         return false;
2098     }
2099 
2100     return ValidateBindVertexArrayBase(context, entryPoint, array);
2101 }
2102 
ValidateIsVertexArray(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)2103 bool ValidateIsVertexArray(const Context *context,
2104                            angle::EntryPoint entryPoint,
2105                            VertexArrayID array)
2106 {
2107     if (context->getClientMajorVersion() < 3)
2108     {
2109         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2110         return false;
2111     }
2112 
2113     return true;
2114 }
2115 
ValidateBindBufferCommon(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)2116 static bool ValidateBindBufferCommon(const Context *context,
2117                                      angle::EntryPoint entryPoint,
2118                                      BufferBinding target,
2119                                      GLuint index,
2120                                      BufferID buffer,
2121                                      GLintptr offset,
2122                                      GLsizeiptr size)
2123 {
2124     if (context->getClientMajorVersion() < 3)
2125     {
2126         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2127         return false;
2128     }
2129 
2130     if (buffer.value != 0 && offset < 0)
2131     {
2132         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
2133         return false;
2134     }
2135 
2136     if (!context->getState().isBindGeneratesResourceEnabled() &&
2137         !context->isBufferGenerated(buffer))
2138     {
2139         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
2140         return false;
2141     }
2142 
2143     const Caps &caps = context->getCaps();
2144     switch (target)
2145     {
2146         case BufferBinding::TransformFeedback:
2147         {
2148             if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
2149             {
2150                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
2151                                        kIndexExceedsTransformFeedbackBufferBindings);
2152                 return false;
2153             }
2154             if (buffer.value != 0 && ((offset % 4) != 0 || (size % 4) != 0))
2155             {
2156                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetAndSizeAlignment);
2157                 return false;
2158             }
2159 
2160             if (context->getState().isTransformFeedbackActive())
2161             {
2162                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackTargetActive);
2163                 return false;
2164             }
2165             break;
2166         }
2167         case BufferBinding::Uniform:
2168         {
2169             if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
2170             {
2171                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
2172                 return false;
2173             }
2174 
2175             ASSERT(caps.uniformBufferOffsetAlignment);
2176             if (buffer.value != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
2177             {
2178                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformBufferOffsetAlignment);
2179                 return false;
2180             }
2181             break;
2182         }
2183         case BufferBinding::AtomicCounter:
2184         {
2185             if (context->getClientVersion() < ES_3_1)
2186             {
2187                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
2188                 return false;
2189             }
2190             if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
2191             {
2192                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
2193                                        kIndexExceedsMaxAtomicCounterBufferBindings);
2194                 return false;
2195             }
2196             if (buffer.value != 0 && (offset % 4) != 0)
2197             {
2198                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetAlignment);
2199                 return false;
2200             }
2201             break;
2202         }
2203         case BufferBinding::ShaderStorage:
2204         {
2205             if (context->getClientVersion() < ES_3_1)
2206             {
2207                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
2208                 return false;
2209             }
2210             if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
2211             {
2212                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
2213                 return false;
2214             }
2215             ASSERT(caps.shaderStorageBufferOffsetAlignment);
2216             if (buffer.value != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
2217             {
2218                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kShaderStorageBufferOffsetAlignment);
2219                 return false;
2220             }
2221             break;
2222         }
2223         case BufferBinding::Texture:
2224         {
2225             if (!context->getExtensions().textureBufferAny())
2226             {
2227                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
2228                 return false;
2229             }
2230             if (index != 0)
2231             {
2232                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
2233                 return false;
2234             }
2235             if (buffer.value != 0 && (offset % caps.textureBufferOffsetAlignment) != 0)
2236             {
2237                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureBufferOffsetAlignment);
2238                 return false;
2239             }
2240             break;
2241         }
2242         case BufferBinding::InvalidEnum:
2243             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid);
2244             return false;
2245         default:
2246             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(target));
2247             return false;
2248     }
2249 
2250     return true;
2251 }
2252 
ValidateBindBufferBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer)2253 bool ValidateBindBufferBase(const Context *context,
2254                             angle::EntryPoint entryPoint,
2255                             BufferBinding target,
2256                             GLuint index,
2257                             BufferID buffer)
2258 {
2259     return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, 0, 0);
2260 }
2261 
ValidateBindBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)2262 bool ValidateBindBufferRange(const Context *context,
2263                              angle::EntryPoint entryPoint,
2264                              BufferBinding target,
2265                              GLuint index,
2266                              BufferID buffer,
2267                              GLintptr offset,
2268                              GLsizeiptr size)
2269 {
2270     if (buffer.value != 0 && size <= 0)
2271     {
2272         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBindBufferSize);
2273         return false;
2274     }
2275     return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, offset, size);
2276 }
2277 
ValidateProgramBinary(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLsizei length)2278 bool ValidateProgramBinary(const Context *context,
2279                            angle::EntryPoint entryPoint,
2280                            ShaderProgramID program,
2281                            GLenum binaryFormat,
2282                            const void *binary,
2283                            GLsizei length)
2284 {
2285     if (context->getClientMajorVersion() < 3)
2286     {
2287         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2288         return false;
2289     }
2290 
2291     return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
2292 }
2293 
ValidateGetProgramBinary(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)2294 bool ValidateGetProgramBinary(const Context *context,
2295                               angle::EntryPoint entryPoint,
2296                               ShaderProgramID program,
2297                               GLsizei bufSize,
2298                               const GLsizei *length,
2299                               const GLenum *binaryFormat,
2300                               const void *binary)
2301 {
2302     if (context->getClientMajorVersion() < 3)
2303     {
2304         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2305         return false;
2306     }
2307 
2308     return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
2309                                         binary);
2310 }
2311 
ValidateProgramParameteriBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLint value)2312 bool ValidateProgramParameteriBase(const Context *context,
2313                                    angle::EntryPoint entryPoint,
2314                                    ShaderProgramID program,
2315                                    GLenum pname,
2316                                    GLint value)
2317 {
2318     if (GetValidProgram(context, entryPoint, program) == nullptr)
2319     {
2320         return false;
2321     }
2322 
2323     switch (pname)
2324     {
2325         case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
2326             if (value != GL_FALSE && value != GL_TRUE)
2327             {
2328                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBooleanValue);
2329                 return false;
2330             }
2331             break;
2332 
2333         case GL_PROGRAM_SEPARABLE:
2334             if (context->getClientVersion() < ES_3_1)
2335             {
2336                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES31Required);
2337                 return false;
2338             }
2339 
2340             if (value != GL_FALSE && value != GL_TRUE)
2341             {
2342                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBooleanValue);
2343                 return false;
2344             }
2345             break;
2346 
2347         default:
2348             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2349             return false;
2350     }
2351 
2352     return true;
2353 }
2354 
ValidateProgramParameteri(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLint value)2355 bool ValidateProgramParameteri(const Context *context,
2356                                angle::EntryPoint entryPoint,
2357                                ShaderProgramID program,
2358                                GLenum pname,
2359                                GLint value)
2360 {
2361     if (context->getClientMajorVersion() < 3)
2362     {
2363         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2364         return false;
2365     }
2366 
2367     return ValidateProgramParameteriBase(context, entryPoint, program, pname, value);
2368 }
2369 
ValidateBlitFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2370 bool ValidateBlitFramebuffer(const Context *context,
2371                              angle::EntryPoint entryPoint,
2372                              GLint srcX0,
2373                              GLint srcY0,
2374                              GLint srcX1,
2375                              GLint srcY1,
2376                              GLint dstX0,
2377                              GLint dstY0,
2378                              GLint dstX1,
2379                              GLint dstY1,
2380                              GLbitfield mask,
2381                              GLenum filter)
2382 {
2383     if (context->getClientMajorVersion() < 3 && !context->getExtensions().framebufferBlitNV)
2384     {
2385         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2386         return false;
2387     }
2388 
2389     return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
2390                                              dstY0, dstX1, dstY1, mask, filter);
2391 }
2392 
ValidateClearBufferiv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLint * value)2393 bool ValidateClearBufferiv(const Context *context,
2394                            angle::EntryPoint entryPoint,
2395                            GLenum buffer,
2396                            GLint drawbuffer,
2397                            const GLint *value)
2398 {
2399     switch (buffer)
2400     {
2401         case GL_COLOR:
2402             if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2403                                                     context->getMutableErrorSetForValidation(),
2404                                                     entryPoint, drawbuffer, "drawbuffer"))
2405             {
2406                 return false;
2407             }
2408             if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2409             {
2410                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2411                 return false;
2412             }
2413             if (static_cast<size_t>(drawbuffer) >=
2414                 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2415             {
2416                 // Clearing a non-existent draw buffer is a no-op.
2417                 break;
2418             }
2419             if (context->getExtensions().webglCompatibilityANGLE)
2420             {
2421                 constexpr GLenum validComponentTypes[] = {GL_INT};
2422                 if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
2423                                                                  validComponentTypes,
2424                                                                  ArraySize(validComponentTypes)))
2425                 {
2426                     return false;
2427                 }
2428             }
2429             if (context->getExtensions().renderSharedExponentQCOM)
2430             {
2431                 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2432                 {
2433                     return false;
2434                 }
2435             }
2436             break;
2437 
2438         case GL_STENCIL:
2439             if (drawbuffer != 0)
2440             {
2441                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2442                 return false;
2443             }
2444             break;
2445 
2446         default:
2447             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2448             return false;
2449     }
2450 
2451     return ValidateClearBuffer(context, entryPoint);
2452 }
2453 
ValidateClearBufferuiv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLuint * value)2454 bool ValidateClearBufferuiv(const Context *context,
2455                             angle::EntryPoint entryPoint,
2456                             GLenum buffer,
2457                             GLint drawbuffer,
2458                             const GLuint *value)
2459 {
2460     switch (buffer)
2461     {
2462         case GL_COLOR:
2463             if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2464                                                     context->getMutableErrorSetForValidation(),
2465                                                     entryPoint, drawbuffer, "drawbuffer"))
2466             {
2467                 return false;
2468             }
2469             if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2470             {
2471                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2472                 return false;
2473             }
2474             if (static_cast<size_t>(drawbuffer) >=
2475                 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2476             {
2477                 // Clearing a non-existent draw buffer is a no-op.
2478                 break;
2479             }
2480             if (context->getExtensions().webglCompatibilityANGLE)
2481             {
2482                 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
2483                 if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
2484                                                                  validComponentTypes,
2485                                                                  ArraySize(validComponentTypes)))
2486                 {
2487                     return false;
2488                 }
2489             }
2490             if (context->getExtensions().renderSharedExponentQCOM)
2491             {
2492                 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2493                 {
2494                     return false;
2495                 }
2496             }
2497             break;
2498 
2499         default:
2500             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2501             return false;
2502     }
2503 
2504     return ValidateClearBuffer(context, entryPoint);
2505 }
2506 
ValidateClearBufferfv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLfloat * value)2507 bool ValidateClearBufferfv(const Context *context,
2508                            angle::EntryPoint entryPoint,
2509                            GLenum buffer,
2510                            GLint drawbuffer,
2511                            const GLfloat *value)
2512 {
2513     switch (buffer)
2514     {
2515         case GL_COLOR:
2516             if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2517                                                     context->getMutableErrorSetForValidation(),
2518                                                     entryPoint, drawbuffer, "drawbuffer"))
2519             {
2520                 return false;
2521             }
2522             if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2523             {
2524                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2525                 return false;
2526             }
2527             if (static_cast<size_t>(drawbuffer) >=
2528                 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2529             {
2530                 // Clearing a non-existent draw buffer is a no-op.
2531                 break;
2532             }
2533             if (context->getExtensions().webglCompatibilityANGLE)
2534             {
2535                 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2536                                                           GL_SIGNED_NORMALIZED};
2537                 if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
2538                                                                  validComponentTypes,
2539                                                                  ArraySize(validComponentTypes)))
2540                 {
2541                     return false;
2542                 }
2543             }
2544             if (context->getExtensions().renderSharedExponentQCOM)
2545             {
2546                 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2547                 {
2548                     return false;
2549                 }
2550             }
2551             break;
2552 
2553         case GL_DEPTH:
2554             if (drawbuffer != 0)
2555             {
2556                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2557                 return false;
2558             }
2559             break;
2560 
2561         default:
2562             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2563             return false;
2564     }
2565 
2566     return ValidateClearBuffer(context, entryPoint);
2567 }
2568 
ValidateClearBufferfi(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)2569 bool ValidateClearBufferfi(const Context *context,
2570                            angle::EntryPoint entryPoint,
2571                            GLenum buffer,
2572                            GLint drawbuffer,
2573                            GLfloat depth,
2574                            GLint stencil)
2575 {
2576     switch (buffer)
2577     {
2578         case GL_DEPTH_STENCIL:
2579             if (drawbuffer != 0)
2580             {
2581                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2582                 return false;
2583             }
2584             break;
2585 
2586         default:
2587             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2588             return false;
2589     }
2590 
2591     return ValidateClearBuffer(context, entryPoint);
2592 }
2593 
ValidateDrawBuffers(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const GLenum * bufs)2594 bool ValidateDrawBuffers(const Context *context,
2595                          angle::EntryPoint entryPoint,
2596                          GLsizei n,
2597                          const GLenum *bufs)
2598 {
2599     if (context->getClientMajorVersion() < 3)
2600     {
2601         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2602         return false;
2603     }
2604 
2605     return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
2606 }
2607 
ValidateCopyTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)2608 bool ValidateCopyTexSubImage3D(const Context *context,
2609                                angle::EntryPoint entryPoint,
2610                                TextureTarget target,
2611                                GLint level,
2612                                GLint xoffset,
2613                                GLint yoffset,
2614                                GLint zoffset,
2615                                GLint x,
2616                                GLint y,
2617                                GLsizei width,
2618                                GLsizei height)
2619 {
2620     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2621     {
2622         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2623         return false;
2624     }
2625 
2626     return ValidateES3CopyTexImage3DParameters(context, entryPoint, target, level, GL_NONE, true,
2627                                                xoffset, yoffset, zoffset, x, y, width, height, 0);
2628 }
2629 
ValidateCopyTexture3DANGLE(const Context * context,angle::EntryPoint entryPoint,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2630 bool ValidateCopyTexture3DANGLE(const Context *context,
2631                                 angle::EntryPoint entryPoint,
2632                                 TextureID sourceId,
2633                                 GLint sourceLevel,
2634                                 TextureTarget destTarget,
2635                                 TextureID destId,
2636                                 GLint destLevel,
2637                                 GLint internalFormat,
2638                                 GLenum destType,
2639                                 GLboolean unpackFlipY,
2640                                 GLboolean unpackPremultiplyAlpha,
2641                                 GLboolean unpackUnmultiplyAlpha)
2642 {
2643     const Texture *source = context->getTexture(sourceId);
2644     if (source == nullptr)
2645     {
2646         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
2647         return false;
2648     }
2649 
2650     TextureType sourceType = source->getType();
2651     ASSERT(sourceType != TextureType::CubeMap);
2652     TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2653     const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2654 
2655     const Texture *dest = context->getTexture(destId);
2656     if (dest == nullptr)
2657     {
2658         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
2659         return false;
2660     }
2661 
2662     if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
2663                                      sourceFormat.info->internalFormat, dest, destLevel,
2664                                      internalFormat, destTarget))
2665     {
2666         return false;
2667     }
2668 
2669     if (!ValidMipLevel(context, source->getType(), sourceLevel))
2670     {
2671         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
2672         return false;
2673     }
2674 
2675     GLsizei sourceWidth  = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
2676     GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
2677     if (sourceWidth == 0 || sourceHeight == 0)
2678     {
2679         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureSize);
2680         return false;
2681     }
2682 
2683     if (dest->getImmutableFormat())
2684     {
2685         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDestinationImmutable);
2686         return false;
2687     }
2688 
2689     return true;
2690 }
2691 
ValidateCopySubTexture3DANGLE(const Context * context,angle::EntryPoint entryPoint,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLint z,GLsizei width,GLsizei height,GLsizei depth,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2692 bool ValidateCopySubTexture3DANGLE(const Context *context,
2693                                    angle::EntryPoint entryPoint,
2694                                    TextureID sourceId,
2695                                    GLint sourceLevel,
2696                                    TextureTarget destTarget,
2697                                    TextureID destId,
2698                                    GLint destLevel,
2699                                    GLint xoffset,
2700                                    GLint yoffset,
2701                                    GLint zoffset,
2702                                    GLint x,
2703                                    GLint y,
2704                                    GLint z,
2705                                    GLsizei width,
2706                                    GLsizei height,
2707                                    GLsizei depth,
2708                                    GLboolean unpackFlipY,
2709                                    GLboolean unpackPremultiplyAlpha,
2710                                    GLboolean unpackUnmultiplyAlpha)
2711 {
2712     const Texture *source = context->getTexture(sourceId);
2713     if (source == nullptr)
2714     {
2715         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
2716         return false;
2717     }
2718 
2719     TextureType sourceType = source->getType();
2720     ASSERT(sourceType != TextureType::CubeMap);
2721     TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2722     const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2723 
2724     const Texture *dest = context->getTexture(destId);
2725     if (dest == nullptr)
2726     {
2727         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
2728         return false;
2729     }
2730 
2731     const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
2732 
2733     if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
2734                                      sourceFormat.info->internalFormat, dest, destLevel,
2735                                      destFormat.internalFormat, destTarget))
2736     {
2737         return false;
2738     }
2739 
2740     if (x < 0 || y < 0 || z < 0)
2741     {
2742         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeXYZ);
2743         return false;
2744     }
2745 
2746     if (width < 0 || height < 0 || depth < 0)
2747     {
2748         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeHeightWidthDepth);
2749         return false;
2750     }
2751 
2752     if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
2753         static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
2754         static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
2755     {
2756         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
2757         return false;
2758     }
2759 
2760     if (TextureTargetToType(destTarget) != dest->getType())
2761     {
2762         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTextureType);
2763         return false;
2764     }
2765 
2766     if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2767     {
2768         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
2769         return false;
2770     }
2771 
2772     if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
2773         static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
2774         static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
2775     {
2776         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDestinationTextureTooSmall);
2777         return false;
2778     }
2779 
2780     return true;
2781 }
2782 
ValidateTexImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)2783 bool ValidateTexImage3D(const Context *context,
2784                         angle::EntryPoint entryPoint,
2785                         TextureTarget target,
2786                         GLint level,
2787                         GLint internalformat,
2788                         GLsizei width,
2789                         GLsizei height,
2790                         GLsizei depth,
2791                         GLint border,
2792                         GLenum format,
2793                         GLenum type,
2794                         const void *pixels)
2795 {
2796     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2797     {
2798         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2799         return false;
2800     }
2801 
2802     return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
2803                                            false, false, 0, 0, 0, width, height, depth, border,
2804                                            format, type, -1, pixels);
2805 }
2806 
ValidateTexImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2807 bool ValidateTexImage3DRobustANGLE(const Context *context,
2808                                    angle::EntryPoint entryPoint,
2809                                    TextureTarget target,
2810                                    GLint level,
2811                                    GLint internalformat,
2812                                    GLsizei width,
2813                                    GLsizei height,
2814                                    GLsizei depth,
2815                                    GLint border,
2816                                    GLenum format,
2817                                    GLenum type,
2818                                    GLsizei bufSize,
2819                                    const void *pixels)
2820 {
2821     if (context->getClientMajorVersion() < 3)
2822     {
2823         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2824         return false;
2825     }
2826 
2827     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2828     {
2829         return false;
2830     }
2831 
2832     return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
2833                                            false, false, 0, 0, 0, width, height, depth, border,
2834                                            format, type, bufSize, pixels);
2835 }
2836 
ValidateTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2837 bool ValidateTexSubImage3D(const Context *context,
2838                            angle::EntryPoint entryPoint,
2839                            TextureTarget target,
2840                            GLint level,
2841                            GLint xoffset,
2842                            GLint yoffset,
2843                            GLint zoffset,
2844                            GLsizei width,
2845                            GLsizei height,
2846                            GLsizei depth,
2847                            GLenum format,
2848                            GLenum type,
2849                            const void *pixels)
2850 {
2851     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2852     {
2853         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2854         return false;
2855     }
2856 
2857     return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
2858                                            xoffset, yoffset, zoffset, width, height, depth, 0,
2859                                            format, type, -1, pixels);
2860 }
2861 
ValidateTexSubImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2862 bool ValidateTexSubImage3DRobustANGLE(const Context *context,
2863                                       angle::EntryPoint entryPoint,
2864                                       TextureTarget target,
2865                                       GLint level,
2866                                       GLint xoffset,
2867                                       GLint yoffset,
2868                                       GLint zoffset,
2869                                       GLsizei width,
2870                                       GLsizei height,
2871                                       GLsizei depth,
2872                                       GLenum format,
2873                                       GLenum type,
2874                                       GLsizei bufSize,
2875                                       const void *pixels)
2876 {
2877     if (context->getClientMajorVersion() < 3)
2878     {
2879         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2880         return false;
2881     }
2882 
2883     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2884     {
2885         return false;
2886     }
2887 
2888     return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
2889                                            xoffset, yoffset, zoffset, width, height, depth, 0,
2890                                            format, type, bufSize, pixels);
2891 }
2892 
ValidateCompressedTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)2893 bool ValidateCompressedTexSubImage3D(const Context *context,
2894                                      angle::EntryPoint entryPoint,
2895                                      TextureTarget target,
2896                                      GLint level,
2897                                      GLint xoffset,
2898                                      GLint yoffset,
2899                                      GLint zoffset,
2900                                      GLsizei width,
2901                                      GLsizei height,
2902                                      GLsizei depth,
2903                                      GLenum format,
2904                                      GLsizei imageSize,
2905                                      const void *data)
2906 {
2907     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2908     {
2909         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2910         return false;
2911     }
2912 
2913     if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, true,
2914                                          xoffset, yoffset, zoffset, width, height, depth, 0, format,
2915                                          GL_NONE, -1, data))
2916     {
2917         return false;
2918     }
2919 
2920     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2921 
2922     if (!formatInfo.compressed)
2923     {
2924         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidCompressedFormat);
2925         return false;
2926     }
2927 
2928     GLuint blockSize = 0;
2929     if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
2930     {
2931         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
2932         return false;
2933     }
2934 
2935     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2936     {
2937         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2938         return false;
2939     }
2940 
2941     if (data == nullptr)
2942     {
2943         if (context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
2944         {
2945             // If data is null, we need an unpack buffer to read from
2946             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
2947             return false;
2948         }
2949 
2950         if (context->getTextureByTarget(target)->isCompressedFormatEmulated(context, target, level))
2951         {
2952             // TODO (anglebug.com/7464): Can't populate from a buffer using emulated format
2953             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEmulatedFormat);
2954             return false;
2955         }
2956     }
2957 
2958     return true;
2959 }
2960 
ValidateCompressedTexSubImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2961 bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
2962                                                 angle::EntryPoint entryPoint,
2963                                                 TextureTarget target,
2964                                                 GLint level,
2965                                                 GLint xoffset,
2966                                                 GLint yoffset,
2967                                                 GLint zoffset,
2968                                                 GLsizei width,
2969                                                 GLsizei height,
2970                                                 GLsizei depth,
2971                                                 GLenum format,
2972                                                 GLsizei imageSize,
2973                                                 GLsizei dataSize,
2974                                                 const void *data)
2975 {
2976     if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
2977     {
2978         return false;
2979     }
2980 
2981     return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
2982                                            zoffset, width, height, depth, format, imageSize, data);
2983 }
2984 
ValidateGenQueries(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * queries)2985 bool ValidateGenQueries(const Context *context,
2986                         angle::EntryPoint entryPoint,
2987                         GLsizei n,
2988                         const QueryID *queries)
2989 {
2990     return ValidateGenOrDeleteES3(context, entryPoint, n);
2991 }
2992 
ValidateDeleteQueries(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * queries)2993 bool ValidateDeleteQueries(const Context *context,
2994                            angle::EntryPoint entryPoint,
2995                            GLsizei n,
2996                            const QueryID *queries)
2997 {
2998     return ValidateGenOrDeleteES3(context, entryPoint, n);
2999 }
3000 
ValidateGenSamplers(const Context * context,angle::EntryPoint entryPoint,GLsizei count,const SamplerID * samplers)3001 bool ValidateGenSamplers(const Context *context,
3002                          angle::EntryPoint entryPoint,
3003                          GLsizei count,
3004                          const SamplerID *samplers)
3005 {
3006     return ValidateGenOrDeleteCountES3(context, entryPoint, count);
3007 }
3008 
ValidateDeleteSamplers(const Context * context,angle::EntryPoint entryPoint,GLsizei count,const SamplerID * samplers)3009 bool ValidateDeleteSamplers(const Context *context,
3010                             angle::EntryPoint entryPoint,
3011                             GLsizei count,
3012                             const SamplerID *samplers)
3013 {
3014     return ValidateGenOrDeleteCountES3(context, entryPoint, count);
3015 }
3016 
ValidateGenTransformFeedbacks(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const TransformFeedbackID * ids)3017 bool ValidateGenTransformFeedbacks(const Context *context,
3018                                    angle::EntryPoint entryPoint,
3019                                    GLsizei n,
3020                                    const TransformFeedbackID *ids)
3021 {
3022     return ValidateGenOrDeleteES3(context, entryPoint, n);
3023 }
3024 
ValidateDeleteTransformFeedbacks(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const TransformFeedbackID * ids)3025 bool ValidateDeleteTransformFeedbacks(const Context *context,
3026                                       angle::EntryPoint entryPoint,
3027                                       GLsizei n,
3028                                       const TransformFeedbackID *ids)
3029 {
3030     if (!ValidateGenOrDeleteES3(context, entryPoint, n))
3031     {
3032         return false;
3033     }
3034     for (GLint i = 0; i < n; ++i)
3035     {
3036         auto *transformFeedback = context->getTransformFeedback(ids[i]);
3037         if (transformFeedback != nullptr && transformFeedback->isActive())
3038         {
3039             // ES 3.0.4 section 2.15.1 page 86
3040             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackActiveDelete);
3041             return false;
3042         }
3043     }
3044     return true;
3045 }
3046 
ValidateGenVertexArrays(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const VertexArrayID * arrays)3047 bool ValidateGenVertexArrays(const Context *context,
3048                              angle::EntryPoint entryPoint,
3049                              GLsizei n,
3050                              const VertexArrayID *arrays)
3051 {
3052     return ValidateGenOrDeleteES3(context, entryPoint, n);
3053 }
3054 
ValidateDeleteVertexArrays(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const VertexArrayID * arrays)3055 bool ValidateDeleteVertexArrays(const Context *context,
3056                                 angle::EntryPoint entryPoint,
3057                                 GLsizei n,
3058                                 const VertexArrayID *arrays)
3059 {
3060     return ValidateGenOrDeleteES3(context, entryPoint, n);
3061 }
3062 
ValidateBeginTransformFeedback(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode primitiveMode)3063 bool ValidateBeginTransformFeedback(const Context *context,
3064                                     angle::EntryPoint entryPoint,
3065                                     PrimitiveMode primitiveMode)
3066 {
3067     if (context->getClientMajorVersion() < 3)
3068     {
3069         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3070         return false;
3071     }
3072     switch (primitiveMode)
3073     {
3074         case PrimitiveMode::Triangles:
3075         case PrimitiveMode::Lines:
3076         case PrimitiveMode::Points:
3077             break;
3078 
3079         default:
3080             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPrimitiveMode);
3081             return false;
3082     }
3083 
3084     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3085     ASSERT(transformFeedback != nullptr);
3086 
3087     if (transformFeedback->isActive())
3088     {
3089         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransfomFeedbackAlreadyActive);
3090         return false;
3091     }
3092 
3093     for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
3094     {
3095         const OffsetBindingPointer<Buffer> &buffer = transformFeedback->getIndexedBuffer(i);
3096         if (buffer.get())
3097         {
3098             if (buffer->isMapped())
3099             {
3100                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
3101                 return false;
3102             }
3103             if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
3104                  context->getExtensions().webglCompatibilityANGLE) &&
3105                 buffer->isDoubleBoundForTransformFeedback())
3106             {
3107                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
3108                                        kTransformFeedbackBufferMultipleOutputs);
3109                 return false;
3110             }
3111         }
3112     }
3113 
3114     const ProgramExecutable *programExecutable =
3115         context->getState().getLinkedProgramExecutable(context);
3116     if (!programExecutable)
3117     {
3118         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotBound);
3119         return false;
3120     }
3121 
3122     if (programExecutable->getLinkedTransformFeedbackVaryings().empty())
3123     {
3124         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoTransformFeedbackOutputVariables);
3125         return false;
3126     }
3127 
3128     if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
3129     {
3130         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
3131         return false;
3132     }
3133 
3134     return true;
3135 }
3136 
ValidateGetBufferPointerv(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,void * const * params)3137 bool ValidateGetBufferPointerv(const Context *context,
3138                                angle::EntryPoint entryPoint,
3139                                BufferBinding target,
3140                                GLenum pname,
3141                                void *const *params)
3142 {
3143     if (context->getClientMajorVersion() < 3)
3144     {
3145         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3146         return false;
3147     }
3148 
3149     return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
3150 }
3151 
ValidateGetBufferPointervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)3152 bool ValidateGetBufferPointervRobustANGLE(const Context *context,
3153                                           angle::EntryPoint entryPoint,
3154                                           BufferBinding target,
3155                                           GLenum pname,
3156                                           GLsizei bufSize,
3157                                           const GLsizei *length,
3158                                           void *const *params)
3159 {
3160     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3161     {
3162         return false;
3163     }
3164 
3165     GLsizei numParams = 0;
3166 
3167     if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES)
3168     {
3169         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3170         return false;
3171     }
3172 
3173     if (!ValidateGetBufferPointervBase(context, entryPoint, target, pname, &numParams, params))
3174     {
3175         return false;
3176     }
3177 
3178     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3179     {
3180         return false;
3181     }
3182 
3183     SetRobustLengthParam(length, numParams);
3184 
3185     return true;
3186 }
3187 
ValidateUnmapBuffer(const Context * context,angle::EntryPoint entryPoint,BufferBinding target)3188 bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target)
3189 {
3190     if (context->getClientMajorVersion() < 3)
3191     {
3192         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3193         return false;
3194     }
3195 
3196     return ValidateUnmapBufferBase(context, entryPoint, target);
3197 }
3198 
ValidateMapBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3199 bool ValidateMapBufferRange(const Context *context,
3200                             angle::EntryPoint entryPoint,
3201                             BufferBinding target,
3202                             GLintptr offset,
3203                             GLsizeiptr length,
3204                             GLbitfield access)
3205 {
3206     if (context->getClientMajorVersion() < 3)
3207     {
3208         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3209         return false;
3210     }
3211 
3212     return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
3213 }
3214 
ValidateFlushMappedBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length)3215 bool ValidateFlushMappedBufferRange(const Context *context,
3216                                     angle::EntryPoint entryPoint,
3217                                     BufferBinding target,
3218                                     GLintptr offset,
3219                                     GLsizeiptr length)
3220 {
3221     if (context->getClientMajorVersion() < 3)
3222     {
3223         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3224         return false;
3225     }
3226 
3227     return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
3228 }
3229 
ValidateIndexedStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,GLsizei * length)3230 bool ValidateIndexedStateQuery(const Context *context,
3231                                angle::EntryPoint entryPoint,
3232                                GLenum pname,
3233                                GLuint index,
3234                                GLsizei *length)
3235 {
3236     if (length)
3237     {
3238         *length = 0;
3239     }
3240 
3241     GLenum nativeType;
3242     unsigned int numParams;
3243     if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
3244     {
3245         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
3246         return false;
3247     }
3248 
3249     const Caps &caps = context->getCaps();
3250     switch (pname)
3251     {
3252         case GL_BLEND_SRC_RGB:
3253         case GL_BLEND_SRC_ALPHA:
3254         case GL_BLEND_DST_RGB:
3255         case GL_BLEND_DST_ALPHA:
3256         case GL_BLEND_EQUATION_RGB:
3257         case GL_BLEND_EQUATION_ALPHA:
3258         case GL_COLOR_WRITEMASK:
3259             if (!context->getExtensions().drawBuffersIndexedAny())
3260             {
3261                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kDrawBuffersIndexedExtensionNotAvailable);
3262                 return false;
3263             }
3264             if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
3265             {
3266                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
3267                 return false;
3268             }
3269             break;
3270         case GL_TRANSFORM_FEEDBACK_BUFFER_START:
3271         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
3272         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3273             if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
3274             {
3275                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxTransformFeedbackAttribs);
3276                 return false;
3277             }
3278             break;
3279 
3280         case GL_UNIFORM_BUFFER_START:
3281         case GL_UNIFORM_BUFFER_SIZE:
3282         case GL_UNIFORM_BUFFER_BINDING:
3283             if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
3284             {
3285                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
3286                 return false;
3287             }
3288             break;
3289 
3290         case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
3291         case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
3292             if (index >= 3u)
3293             {
3294                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxWorkgroupDimensions);
3295                 return false;
3296             }
3297             break;
3298 
3299         case GL_ATOMIC_COUNTER_BUFFER_START:
3300         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
3301         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3302             if (context->getClientVersion() < ES_3_1)
3303             {
3304                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3305                 return false;
3306             }
3307             if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
3308             {
3309                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
3310                                        kIndexExceedsMaxAtomicCounterBufferBindings);
3311                 return false;
3312             }
3313             break;
3314 
3315         case GL_SHADER_STORAGE_BUFFER_START:
3316         case GL_SHADER_STORAGE_BUFFER_SIZE:
3317         case GL_SHADER_STORAGE_BUFFER_BINDING:
3318             if (context->getClientVersion() < ES_3_1)
3319             {
3320                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3321                 return false;
3322             }
3323             if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
3324             {
3325                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
3326                 return false;
3327             }
3328             break;
3329 
3330         case GL_VERTEX_BINDING_BUFFER:
3331         case GL_VERTEX_BINDING_DIVISOR:
3332         case GL_VERTEX_BINDING_OFFSET:
3333         case GL_VERTEX_BINDING_STRIDE:
3334             if (context->getClientVersion() < ES_3_1)
3335             {
3336                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3337                 return false;
3338             }
3339             if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3340             {
3341                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3342                 return false;
3343             }
3344             break;
3345         case GL_SAMPLE_MASK_VALUE:
3346             if (context->getClientVersion() < ES_3_1)
3347             {
3348                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3349                 return false;
3350             }
3351             if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
3352             {
3353                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
3354                 return false;
3355             }
3356             break;
3357         case GL_IMAGE_BINDING_NAME:
3358         case GL_IMAGE_BINDING_LEVEL:
3359         case GL_IMAGE_BINDING_LAYERED:
3360         case GL_IMAGE_BINDING_LAYER:
3361         case GL_IMAGE_BINDING_ACCESS:
3362         case GL_IMAGE_BINDING_FORMAT:
3363             if (context->getClientVersion() < ES_3_1)
3364             {
3365                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3366                 return false;
3367             }
3368             if (index >= static_cast<GLuint>(caps.maxImageUnits))
3369             {
3370                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxImageUnits);
3371                 return false;
3372             }
3373             break;
3374         default:
3375             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3376             return false;
3377     }
3378 
3379     if (length)
3380     {
3381         if (pname == GL_COLOR_WRITEMASK)
3382         {
3383             *length = 4;
3384         }
3385         else
3386         {
3387             *length = 1;
3388         }
3389     }
3390 
3391     return true;
3392 }
3393 
ValidateGetIntegeri_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint * data)3394 bool ValidateGetIntegeri_v(const Context *context,
3395                            angle::EntryPoint entryPoint,
3396                            GLenum target,
3397                            GLuint index,
3398                            const GLint *data)
3399 {
3400     if (context->getClientVersion() < ES_3_0)
3401     {
3402         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3403         return false;
3404     }
3405     return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3406 }
3407 
ValidateGetIntegeri_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint * data)3408 bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
3409                                       angle::EntryPoint entryPoint,
3410                                       GLenum target,
3411                                       GLuint index,
3412                                       GLsizei bufSize,
3413                                       const GLsizei *length,
3414                                       const GLint *data)
3415 {
3416     if (context->getClientVersion() < ES_3_0)
3417     {
3418         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3419         return false;
3420     }
3421 
3422     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3423     {
3424         return false;
3425     }
3426 
3427     GLsizei numParams = 0;
3428 
3429     if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3430     {
3431         return false;
3432     }
3433 
3434     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3435     {
3436         return false;
3437     }
3438 
3439     SetRobustLengthParam(length, numParams);
3440 
3441     return true;
3442 }
3443 
ValidateGetInteger64i_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint64 * data)3444 bool ValidateGetInteger64i_v(const Context *context,
3445                              angle::EntryPoint entryPoint,
3446                              GLenum target,
3447                              GLuint index,
3448                              const GLint64 *data)
3449 {
3450     if (context->getClientVersion() < ES_3_0)
3451     {
3452         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3453         return false;
3454     }
3455     return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3456 }
3457 
ValidateGetInteger64i_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint64 * data)3458 bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
3459                                         angle::EntryPoint entryPoint,
3460                                         GLenum target,
3461                                         GLuint index,
3462                                         GLsizei bufSize,
3463                                         const GLsizei *length,
3464                                         const GLint64 *data)
3465 {
3466     if (context->getClientVersion() < ES_3_0)
3467     {
3468         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3469         return false;
3470     }
3471 
3472     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3473     {
3474         return false;
3475     }
3476 
3477     GLsizei numParams = 0;
3478 
3479     if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3480     {
3481         return false;
3482     }
3483 
3484     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3485     {
3486         return false;
3487     }
3488 
3489     SetRobustLengthParam(length, numParams);
3490 
3491     return true;
3492 }
3493 
ValidateCopyBufferSubData(const Context * context,angle::EntryPoint entryPoint,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)3494 bool ValidateCopyBufferSubData(const Context *context,
3495                                angle::EntryPoint entryPoint,
3496                                BufferBinding readTarget,
3497                                BufferBinding writeTarget,
3498                                GLintptr readOffset,
3499                                GLintptr writeOffset,
3500                                GLsizeiptr size)
3501 {
3502     if (context->getClientMajorVersion() < 3)
3503     {
3504         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3505         return false;
3506     }
3507 
3508     if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
3509     {
3510         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
3511         return false;
3512     }
3513 
3514     Buffer *readBuffer  = context->getState().getTargetBuffer(readTarget);
3515     Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
3516 
3517     if (!readBuffer || !writeBuffer)
3518     {
3519         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
3520         return false;
3521     }
3522 
3523     // EXT_buffer_storage allows persistently mapped buffers to be updated via glCopyBufferSubData
3524     bool isReadPersistent  = (readBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3525     bool isWritePersistent = (writeBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3526 
3527     // Verify that readBuffer and writeBuffer are not currently mapped unless persistent
3528     if ((readBuffer->isMapped() && !isReadPersistent) ||
3529         (writeBuffer->isMapped() && !isWritePersistent))
3530     {
3531         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
3532         return false;
3533     }
3534 
3535     if (readBuffer->hasWebGLXFBBindingConflict(context->isWebGL()) ||
3536         writeBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
3537     {
3538         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3539         return false;
3540     }
3541 
3542     CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
3543     CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
3544     CheckedNumeric<GLintptr> checkedSize(size);
3545 
3546     auto checkedReadSum  = checkedReadOffset + checkedSize;
3547     auto checkedWriteSum = checkedWriteOffset + checkedSize;
3548 
3549     if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
3550         !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
3551         !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
3552     {
3553         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3554         return false;
3555     }
3556 
3557     if (readOffset < 0 || writeOffset < 0)
3558     {
3559         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3560         return false;
3561     }
3562 
3563     if (size < 0)
3564     {
3565         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3566         return false;
3567     }
3568 
3569     if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
3570         checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
3571     {
3572         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBufferOffsetOverflow);
3573         return false;
3574     }
3575 
3576     if (readBuffer == writeBuffer)
3577     {
3578         auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
3579         if (!checkedOffsetDiff.IsValid())
3580         {
3581             // This shold not be possible.
3582             UNREACHABLE();
3583             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3584             return false;
3585         }
3586 
3587         if (checkedOffsetDiff.ValueOrDie() < size)
3588         {
3589             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCopyAlias);
3590             return false;
3591         }
3592     }
3593 
3594     return true;
3595 }
3596 
ValidateGetStringi(const Context * context,angle::EntryPoint entryPoint,GLenum name,GLuint index)3597 bool ValidateGetStringi(const Context *context,
3598                         angle::EntryPoint entryPoint,
3599                         GLenum name,
3600                         GLuint index)
3601 {
3602     if (context->getClientMajorVersion() < 3)
3603     {
3604         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3605         return false;
3606     }
3607 
3608     switch (name)
3609     {
3610         case GL_EXTENSIONS:
3611             if (index >= context->getExtensionStringCount())
3612             {
3613                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsNumExtensions);
3614                 return false;
3615             }
3616             break;
3617 
3618         case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3619             if (!context->getExtensions().requestExtensionANGLE)
3620             {
3621                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
3622                 return false;
3623             }
3624             if (index >= context->getRequestableExtensionStringCount())
3625             {
3626                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsNumRequestableExtensions);
3627                 return false;
3628             }
3629             break;
3630 
3631         default:
3632             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
3633             return false;
3634     }
3635 
3636     return true;
3637 }
3638 
ValidateRenderbufferStorageMultisample(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3639 bool ValidateRenderbufferStorageMultisample(const Context *context,
3640                                             angle::EntryPoint entryPoint,
3641                                             GLenum target,
3642                                             GLsizei samples,
3643                                             GLenum internalformat,
3644                                             GLsizei width,
3645                                             GLsizei height)
3646 {
3647     if (context->getClientMajorVersion() < 3)
3648     {
3649         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3650         return false;
3651     }
3652 
3653     if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
3654                                                    internalformat, width, height))
3655     {
3656         return false;
3657     }
3658 
3659     // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
3660     // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
3661     // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
3662     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
3663     if (formatInfo.isInt())
3664     {
3665         if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
3666             samples > context->getCaps().maxIntegerSamples)
3667         {
3668             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3669             return false;
3670         }
3671     }
3672 
3673     // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
3674     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3675     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3676     {
3677         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3678         return false;
3679     }
3680 
3681     return true;
3682 }
3683 
ValidateVertexAttribIPointer(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)3684 bool ValidateVertexAttribIPointer(const Context *context,
3685                                   angle::EntryPoint entryPoint,
3686                                   GLuint index,
3687                                   GLint size,
3688                                   VertexAttribType type,
3689                                   GLsizei stride,
3690                                   const void *pointer)
3691 {
3692     if (context->getClientMajorVersion() < 3)
3693     {
3694         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3695         return false;
3696     }
3697 
3698     if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type))
3699     {
3700         return false;
3701     }
3702 
3703     if (stride < 0)
3704     {
3705         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeStride);
3706         return false;
3707     }
3708 
3709     const Caps &caps = context->getCaps();
3710     if (context->getClientVersion() >= ES_3_1)
3711     {
3712         if (stride > caps.maxVertexAttribStride)
3713         {
3714             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
3715             return false;
3716         }
3717 
3718         // [OpenGL ES 3.1] Section 10.3.1 page 245:
3719         // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3720         // validation should be inherited.
3721         if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3722         {
3723             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3724             return false;
3725         }
3726     }
3727 
3728     // [OpenGL ES 3.0.2] Section 2.8 page 24:
3729     // An INVALID_OPERATION error is generated when a non-zero vertex array object
3730     // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3731     // and the pointer argument is not NULL.
3732     if (context->getState().getVertexArrayId().value != 0 &&
3733         context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
3734     {
3735         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kClientDataInVertexArray);
3736         return false;
3737     }
3738 
3739     if (context->getExtensions().webglCompatibilityANGLE)
3740     {
3741         if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, false, stride, pointer,
3742                                               true))
3743         {
3744             return false;
3745         }
3746     }
3747 
3748     return true;
3749 }
3750 
ValidateGetSynciv(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * values)3751 bool ValidateGetSynciv(const Context *context,
3752                        angle::EntryPoint entryPoint,
3753                        SyncID syncPacked,
3754                        GLenum pname,
3755                        GLsizei bufSize,
3756                        const GLsizei *length,
3757                        const GLint *values)
3758 {
3759     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
3760     {
3761         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3762         return false;
3763     }
3764 
3765     if (bufSize < 0)
3766     {
3767         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
3768         return false;
3769     }
3770 
3771     if (context->isContextLost())
3772     {
3773         ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
3774 
3775         if (pname == GL_SYNC_STATUS)
3776         {
3777             // Generate an error but still return true, the context still needs to return a
3778             // value in this case.
3779             return true;
3780         }
3781         else
3782         {
3783             return false;
3784         }
3785     }
3786 
3787     Sync *syncObject = context->getSync(syncPacked);
3788     if (!syncObject)
3789     {
3790         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
3791         return false;
3792     }
3793 
3794     switch (pname)
3795     {
3796         case GL_OBJECT_TYPE:
3797         case GL_SYNC_CONDITION:
3798         case GL_SYNC_FLAGS:
3799         case GL_SYNC_STATUS:
3800             break;
3801 
3802         default:
3803             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
3804             return false;
3805     }
3806 
3807     return true;
3808 }
3809 
ValidateDrawElementsInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei instanceCount)3810 bool ValidateDrawElementsInstanced(const Context *context,
3811                                    angle::EntryPoint entryPoint,
3812                                    PrimitiveMode mode,
3813                                    GLsizei count,
3814                                    DrawElementsType type,
3815                                    const void *indices,
3816                                    GLsizei instanceCount)
3817 {
3818     if (context->getClientMajorVersion() < 3)
3819     {
3820         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3821         return false;
3822     }
3823 
3824     return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3825                                              instanceCount);
3826 }
3827 
ValidateMultiDrawArraysInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)3828 bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
3829                                            angle::EntryPoint entryPoint,
3830                                            PrimitiveMode mode,
3831                                            const GLint *firsts,
3832                                            const GLsizei *counts,
3833                                            const GLsizei *instanceCounts,
3834                                            GLsizei drawcount)
3835 {
3836     if (!context->getExtensions().multiDrawANGLE)
3837     {
3838         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3839         return false;
3840     }
3841     if (context->getClientMajorVersion() < 3)
3842     {
3843         if (!context->getExtensions().instancedArraysAny())
3844         {
3845             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3846             return false;
3847         }
3848         if (!ValidateDrawInstancedANGLE(context, entryPoint))
3849         {
3850             return false;
3851         }
3852     }
3853     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3854     {
3855         if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID],
3856                                              counts[drawID], instanceCounts[drawID]))
3857         {
3858             return false;
3859         }
3860     }
3861     return true;
3862 }
3863 
ValidateMultiDrawElementsInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)3864 bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
3865                                              angle::EntryPoint entryPoint,
3866                                              PrimitiveMode mode,
3867                                              const GLsizei *counts,
3868                                              DrawElementsType type,
3869                                              const GLvoid *const *indices,
3870                                              const GLsizei *instanceCounts,
3871                                              GLsizei drawcount)
3872 {
3873     if (!context->getExtensions().multiDrawANGLE)
3874     {
3875         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3876         return false;
3877     }
3878     if (context->getClientMajorVersion() < 3)
3879     {
3880         if (!context->getExtensions().instancedArraysAny())
3881         {
3882             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3883             return false;
3884         }
3885         if (!ValidateDrawInstancedANGLE(context, entryPoint))
3886         {
3887             return false;
3888         }
3889     }
3890     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3891     {
3892         if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type,
3893                                                indices[drawID], instanceCounts[drawID]))
3894         {
3895             return false;
3896         }
3897     }
3898     return true;
3899 }
3900 
ValidateDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)3901 bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3902                                                   angle::EntryPoint entryPoint,
3903                                                   PrimitiveMode mode,
3904                                                   GLint first,
3905                                                   GLsizei count,
3906                                                   GLsizei instanceCount,
3907                                                   GLuint baseInstance)
3908 {
3909     if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3910     {
3911         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3912         return false;
3913     }
3914 
3915     return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount);
3916 }
3917 
ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const GLvoid * indices,GLsizei instanceCount,GLint baseVertex,GLuint baseInstance)3918 bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3919                                                               angle::EntryPoint entryPoint,
3920                                                               PrimitiveMode mode,
3921                                                               GLsizei count,
3922                                                               DrawElementsType type,
3923                                                               const GLvoid *indices,
3924                                                               GLsizei instanceCount,
3925                                                               GLint baseVertex,
3926                                                               GLuint baseInstance)
3927 {
3928     if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3929     {
3930         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3931         return false;
3932     }
3933 
3934     return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3935                                              instanceCount);
3936 }
3937 
ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode modePacked,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)3938 bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3939                                                        angle::EntryPoint entryPoint,
3940                                                        PrimitiveMode modePacked,
3941                                                        const GLint *firsts,
3942                                                        const GLsizei *counts,
3943                                                        const GLsizei *instanceCounts,
3944                                                        const GLuint *baseInstances,
3945                                                        GLsizei drawcount)
3946 {
3947     if (!context->getExtensions().multiDrawANGLE)
3948     {
3949         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3950         return false;
3951     }
3952     if (drawcount < 0)
3953     {
3954         return false;
3955     }
3956     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3957     {
3958         if (!ValidateDrawArraysInstancedBase(context, entryPoint, modePacked, firsts[drawID],
3959                                              counts[drawID], instanceCounts[drawID]))
3960         {
3961             return false;
3962         }
3963     }
3964     return true;
3965 }
3966 
ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode modePacked,const GLsizei * counts,DrawElementsType typePacked,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)3967 bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3968                                                                    angle::EntryPoint entryPoint,
3969                                                                    PrimitiveMode modePacked,
3970                                                                    const GLsizei *counts,
3971                                                                    DrawElementsType typePacked,
3972                                                                    const GLvoid *const *indices,
3973                                                                    const GLsizei *instanceCounts,
3974                                                                    const GLint *baseVertices,
3975                                                                    const GLuint *baseInstances,
3976                                                                    GLsizei drawcount)
3977 {
3978     if (!context->getExtensions().multiDrawANGLE)
3979     {
3980         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3981         return false;
3982     }
3983     if (drawcount < 0)
3984     {
3985         return false;
3986     }
3987     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3988     {
3989         if (!ValidateDrawElementsInstancedBase(context, entryPoint, modePacked, counts[drawID],
3990                                                typePacked, indices[drawID], instanceCounts[drawID]))
3991         {
3992             return false;
3993         }
3994     }
3995     return true;
3996 }
3997 
ValidateFramebufferTextureMultiviewOVR(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint baseViewIndex,GLsizei numViews)3998 bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
3999                                             angle::EntryPoint entryPoint,
4000                                             GLenum target,
4001                                             GLenum attachment,
4002                                             TextureID texture,
4003                                             GLint level,
4004                                             GLint baseViewIndex,
4005                                             GLsizei numViews)
4006 {
4007     if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment,
4008                                                       texture, level, numViews))
4009     {
4010         return false;
4011     }
4012 
4013     if (texture.value != 0)
4014     {
4015         if (baseViewIndex < 0)
4016         {
4017             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBaseViewIndex);
4018             return false;
4019         }
4020 
4021         Texture *tex = context->getTexture(texture);
4022         ASSERT(tex);
4023 
4024         switch (tex->getType())
4025         {
4026             case TextureType::_2DArray:
4027             case TextureType::_2DMultisampleArray:
4028             {
4029                 if (tex->getType() == TextureType::_2DMultisampleArray)
4030                 {
4031                     if (!context->getExtensions().multiviewMultisampleANGLE)
4032                     {
4033                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureType);
4034                         return false;
4035                     }
4036                 }
4037 
4038                 const Caps &caps = context->getCaps();
4039                 if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
4040                 {
4041                     ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kViewsExceedMaxArrayLayers);
4042                     return false;
4043                 }
4044 
4045                 break;
4046             }
4047             default:
4048                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureType);
4049                 return false;
4050         }
4051 
4052         if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, entryPoint, tex, level))
4053         {
4054             return false;
4055         }
4056     }
4057 
4058     return true;
4059 }
4060 
ValidateUniform1ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0)4061 bool ValidateUniform1ui(const Context *context,
4062                         angle::EntryPoint entryPoint,
4063                         UniformLocation location,
4064                         GLuint v0)
4065 {
4066     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1);
4067 }
4068 
ValidateUniform2ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1)4069 bool ValidateUniform2ui(const Context *context,
4070                         angle::EntryPoint entryPoint,
4071                         UniformLocation location,
4072                         GLuint v0,
4073                         GLuint v1)
4074 {
4075     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1);
4076 }
4077 
ValidateUniform3ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2)4078 bool ValidateUniform3ui(const Context *context,
4079                         angle::EntryPoint entryPoint,
4080                         UniformLocation location,
4081                         GLuint v0,
4082                         GLuint v1,
4083                         GLuint v2)
4084 {
4085     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1);
4086 }
4087 
ValidateUniform4ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)4088 bool ValidateUniform4ui(const Context *context,
4089                         angle::EntryPoint entryPoint,
4090                         UniformLocation location,
4091                         GLuint v0,
4092                         GLuint v1,
4093                         GLuint v2,
4094                         GLuint v3)
4095 {
4096     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1);
4097 }
4098 
ValidateUniform1uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4099 bool ValidateUniform1uiv(const Context *context,
4100                          angle::EntryPoint entryPoint,
4101                          UniformLocation location,
4102                          GLsizei count,
4103                          const GLuint *value)
4104 {
4105     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count);
4106 }
4107 
ValidateUniform2uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4108 bool ValidateUniform2uiv(const Context *context,
4109                          angle::EntryPoint entryPoint,
4110                          UniformLocation location,
4111                          GLsizei count,
4112                          const GLuint *value)
4113 {
4114     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count);
4115 }
4116 
ValidateUniform3uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4117 bool ValidateUniform3uiv(const Context *context,
4118                          angle::EntryPoint entryPoint,
4119                          UniformLocation location,
4120                          GLsizei count,
4121                          const GLuint *value)
4122 {
4123     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count);
4124 }
4125 
ValidateUniform4uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4126 bool ValidateUniform4uiv(const Context *context,
4127                          angle::EntryPoint entryPoint,
4128                          UniformLocation location,
4129                          GLsizei count,
4130                          const GLuint *value)
4131 {
4132     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count);
4133 }
4134 
ValidateIsQuery(const Context * context,angle::EntryPoint entryPoint,QueryID id)4135 bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id)
4136 {
4137     if (context->getClientMajorVersion() < 3)
4138     {
4139         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4140         return false;
4141     }
4142 
4143     return true;
4144 }
4145 
ValidateUniformMatrix2x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4146 bool ValidateUniformMatrix2x3fv(const Context *context,
4147                                 angle::EntryPoint entryPoint,
4148                                 UniformLocation location,
4149                                 GLsizei count,
4150                                 GLboolean transpose,
4151                                 const GLfloat *value)
4152 {
4153     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count,
4154                                     transpose);
4155 }
4156 
ValidateUniformMatrix3x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4157 bool ValidateUniformMatrix3x2fv(const Context *context,
4158                                 angle::EntryPoint entryPoint,
4159                                 UniformLocation location,
4160                                 GLsizei count,
4161                                 GLboolean transpose,
4162                                 const GLfloat *value)
4163 {
4164     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count,
4165                                     transpose);
4166 }
4167 
ValidateUniformMatrix2x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4168 bool ValidateUniformMatrix2x4fv(const Context *context,
4169                                 angle::EntryPoint entryPoint,
4170                                 UniformLocation location,
4171                                 GLsizei count,
4172                                 GLboolean transpose,
4173                                 const GLfloat *value)
4174 {
4175     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count,
4176                                     transpose);
4177 }
4178 
ValidateUniformMatrix4x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4179 bool ValidateUniformMatrix4x2fv(const Context *context,
4180                                 angle::EntryPoint entryPoint,
4181                                 UniformLocation location,
4182                                 GLsizei count,
4183                                 GLboolean transpose,
4184                                 const GLfloat *value)
4185 {
4186     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count,
4187                                     transpose);
4188 }
4189 
ValidateUniformMatrix3x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4190 bool ValidateUniformMatrix3x4fv(const Context *context,
4191                                 angle::EntryPoint entryPoint,
4192                                 UniformLocation location,
4193                                 GLsizei count,
4194                                 GLboolean transpose,
4195                                 const GLfloat *value)
4196 {
4197     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count,
4198                                     transpose);
4199 }
4200 
ValidateUniformMatrix4x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4201 bool ValidateUniformMatrix4x3fv(const Context *context,
4202                                 angle::EntryPoint entryPoint,
4203                                 UniformLocation location,
4204                                 GLsizei count,
4205                                 GLboolean transpose,
4206                                 const GLfloat *value)
4207 {
4208     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count,
4209                                     transpose);
4210 }
4211 
ValidateEndTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4212 bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4213 {
4214     if (context->getClientMajorVersion() < 3)
4215     {
4216         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4217         return false;
4218     }
4219 
4220     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4221     ASSERT(transformFeedback != nullptr);
4222 
4223     if (!transformFeedback->isActive())
4224     {
4225         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4226         return false;
4227     }
4228 
4229     return true;
4230 }
4231 
ValidateTransformFeedbackVaryings(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)4232 bool ValidateTransformFeedbackVaryings(const Context *context,
4233                                        angle::EntryPoint entryPoint,
4234                                        ShaderProgramID program,
4235                                        GLsizei count,
4236                                        const GLchar *const *varyings,
4237                                        GLenum bufferMode)
4238 {
4239     if (context->getClientMajorVersion() < 3)
4240     {
4241         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4242         return false;
4243     }
4244 
4245     if (count < 0)
4246     {
4247         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4248         return false;
4249     }
4250 
4251     switch (bufferMode)
4252     {
4253         case GL_INTERLEAVED_ATTRIBS:
4254             break;
4255         case GL_SEPARATE_ATTRIBS:
4256         {
4257             const Caps &caps = context->getCaps();
4258             if (count > caps.maxTransformFeedbackSeparateAttributes)
4259             {
4260                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTransformFeedbackAttribsCount);
4261                 return false;
4262             }
4263             break;
4264         }
4265         default:
4266             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, bufferMode);
4267             return false;
4268     }
4269 
4270     Program *programObject = GetValidProgram(context, entryPoint, program);
4271     if (!programObject)
4272     {
4273         return false;
4274     }
4275 
4276     return true;
4277 }
4278 
ValidateGetTransformFeedbackVarying(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint index,GLsizei bufSize,const GLsizei * length,const GLsizei * size,const GLenum * type,const GLchar * name)4279 bool ValidateGetTransformFeedbackVarying(const Context *context,
4280                                          angle::EntryPoint entryPoint,
4281                                          ShaderProgramID program,
4282                                          GLuint index,
4283                                          GLsizei bufSize,
4284                                          const GLsizei *length,
4285                                          const GLsizei *size,
4286                                          const GLenum *type,
4287                                          const GLchar *name)
4288 {
4289     if (context->getClientMajorVersion() < 3)
4290     {
4291         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4292         return false;
4293     }
4294 
4295     if (bufSize < 0)
4296     {
4297         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
4298         return false;
4299     }
4300 
4301     Program *programObject = GetValidProgram(context, entryPoint, program);
4302     if (!programObject)
4303     {
4304         return false;
4305     }
4306 
4307     if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
4308     {
4309         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTransformFeedbackVaryingIndexOutOfRange);
4310         return false;
4311     }
4312 
4313     return true;
4314 }
4315 
ValidateBindTransformFeedback(const Context * context,angle::EntryPoint entryPoint,GLenum target,TransformFeedbackID id)4316 bool ValidateBindTransformFeedback(const Context *context,
4317                                    angle::EntryPoint entryPoint,
4318                                    GLenum target,
4319                                    TransformFeedbackID id)
4320 {
4321     if (context->getClientMajorVersion() < 3)
4322     {
4323         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4324         return false;
4325     }
4326 
4327     switch (target)
4328     {
4329         case GL_TRANSFORM_FEEDBACK:
4330         {
4331             // Cannot bind a transform feedback object if the current one is started and not
4332             // paused (3.0.2 pg 85 section 2.14.1)
4333             if (context->getState().isTransformFeedbackActiveUnpaused())
4334             {
4335                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
4336                 return false;
4337             }
4338 
4339             // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
4340             // 2.14.1)
4341             if (!context->isTransformFeedbackGenerated(id))
4342             {
4343                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackDoesNotExist);
4344                 return false;
4345             }
4346         }
4347         break;
4348 
4349         default:
4350             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, target);
4351             return false;
4352     }
4353 
4354     return true;
4355 }
4356 
ValidateIsTransformFeedback(const Context * context,angle::EntryPoint entryPoint,TransformFeedbackID id)4357 bool ValidateIsTransformFeedback(const Context *context,
4358                                  angle::EntryPoint entryPoint,
4359                                  TransformFeedbackID id)
4360 {
4361     if (context->getClientMajorVersion() < 3)
4362     {
4363         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4364         return false;
4365     }
4366 
4367     return true;
4368 }
4369 
ValidatePauseTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4370 bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4371 {
4372     if (context->getClientMajorVersion() < 3)
4373     {
4374         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4375         return false;
4376     }
4377 
4378     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4379     ASSERT(transformFeedback != nullptr);
4380 
4381     // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
4382     if (!transformFeedback->isActive())
4383     {
4384         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4385         return false;
4386     }
4387 
4388     if (transformFeedback->isPaused())
4389     {
4390         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackPaused);
4391         return false;
4392     }
4393 
4394     return true;
4395 }
4396 
ValidateResumeTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4397 bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4398 {
4399     if (context->getClientMajorVersion() < 3)
4400     {
4401         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4402         return false;
4403     }
4404 
4405     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4406     ASSERT(transformFeedback != nullptr);
4407 
4408     // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
4409     if (!transformFeedback->isActive())
4410     {
4411         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4412         return false;
4413     }
4414 
4415     if (!transformFeedback->isPaused())
4416     {
4417         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
4418         return false;
4419     }
4420 
4421     if (!ValidateProgramExecutableXFBBuffersPresent(
4422             context, context->getState().getLinkedProgramExecutable(context)))
4423     {
4424         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
4425         return false;
4426     }
4427 
4428     return true;
4429 }
4430 
ValidateVertexAttribI4i(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,GLint x,GLint y,GLint z,GLint w)4431 bool ValidateVertexAttribI4i(const PrivateState &state,
4432                              ErrorSet *errors,
4433                              angle::EntryPoint entryPoint,
4434                              GLuint index,
4435                              GLint x,
4436                              GLint y,
4437                              GLint z,
4438                              GLint w)
4439 {
4440     if (state.getClientMajorVersion() < 3)
4441     {
4442         errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4443         return false;
4444     }
4445 
4446     return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4447 }
4448 
ValidateVertexAttribI4ui(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)4449 bool ValidateVertexAttribI4ui(const PrivateState &state,
4450                               ErrorSet *errors,
4451                               angle::EntryPoint entryPoint,
4452                               GLuint index,
4453                               GLuint x,
4454                               GLuint y,
4455                               GLuint z,
4456                               GLuint w)
4457 {
4458     if (state.getClientMajorVersion() < 3)
4459     {
4460         errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4461         return false;
4462     }
4463 
4464     return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4465 }
4466 
ValidateVertexAttribI4iv(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,const GLint * v)4467 bool ValidateVertexAttribI4iv(const PrivateState &state,
4468                               ErrorSet *errors,
4469                               angle::EntryPoint entryPoint,
4470                               GLuint index,
4471                               const GLint *v)
4472 {
4473     if (state.getClientMajorVersion() < 3)
4474     {
4475         errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4476         return false;
4477     }
4478 
4479     return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4480 }
4481 
ValidateVertexAttribI4uiv(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,const GLuint * v)4482 bool ValidateVertexAttribI4uiv(const PrivateState &state,
4483                                ErrorSet *errors,
4484                                angle::EntryPoint entryPoint,
4485                                GLuint index,
4486                                const GLuint *v)
4487 {
4488     if (state.getClientMajorVersion() < 3)
4489     {
4490         errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4491         return false;
4492     }
4493 
4494     return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4495 }
4496 
ValidateGetFragDataLocation(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * name)4497 bool ValidateGetFragDataLocation(const Context *context,
4498                                  angle::EntryPoint entryPoint,
4499                                  ShaderProgramID program,
4500                                  const GLchar *name)
4501 {
4502     if (context->getClientMajorVersion() < 3)
4503     {
4504         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4505         return false;
4506     }
4507 
4508     Program *programObject = GetValidProgram(context, entryPoint, program);
4509     if (!programObject)
4510     {
4511         return false;
4512     }
4513 
4514     if (!programObject->isLinked())
4515     {
4516         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
4517         return false;
4518     }
4519 
4520     return true;
4521 }
4522 
ValidateGetUniformIndices(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLchar * const * uniformNames,const GLuint * uniformIndices)4523 bool ValidateGetUniformIndices(const Context *context,
4524                                angle::EntryPoint entryPoint,
4525                                ShaderProgramID program,
4526                                GLsizei uniformCount,
4527                                const GLchar *const *uniformNames,
4528                                const GLuint *uniformIndices)
4529 {
4530     if (context->getClientMajorVersion() < 3)
4531     {
4532         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4533         return false;
4534     }
4535 
4536     if (uniformCount < 0)
4537     {
4538         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4539         return false;
4540     }
4541 
4542     Program *programObject = GetValidProgram(context, entryPoint, program);
4543     if (!programObject)
4544     {
4545         return false;
4546     }
4547 
4548     return true;
4549 }
4550 
ValidateGetActiveUniformsiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,const GLint * params)4551 bool ValidateGetActiveUniformsiv(const Context *context,
4552                                  angle::EntryPoint entryPoint,
4553                                  ShaderProgramID program,
4554                                  GLsizei uniformCount,
4555                                  const GLuint *uniformIndices,
4556                                  GLenum pname,
4557                                  const GLint *params)
4558 {
4559     if (context->getClientMajorVersion() < 3)
4560     {
4561         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4562         return false;
4563     }
4564 
4565     if (uniformCount < 0)
4566     {
4567         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4568         return false;
4569     }
4570 
4571     Program *programObject = GetValidProgram(context, entryPoint, program);
4572     if (!programObject)
4573     {
4574         return false;
4575     }
4576 
4577     switch (pname)
4578     {
4579         case GL_UNIFORM_TYPE:
4580         case GL_UNIFORM_SIZE:
4581             break;
4582         case GL_UNIFORM_NAME_LENGTH:
4583             if (context->getExtensions().webglCompatibilityANGLE)
4584             {
4585                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
4586                 return false;
4587             }
4588             break;
4589         case GL_UNIFORM_BLOCK_INDEX:
4590         case GL_UNIFORM_OFFSET:
4591         case GL_UNIFORM_ARRAY_STRIDE:
4592         case GL_UNIFORM_MATRIX_STRIDE:
4593         case GL_UNIFORM_IS_ROW_MAJOR:
4594             break;
4595 
4596         default:
4597             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
4598             return false;
4599     }
4600 
4601     if (uniformCount > programObject->getActiveUniformCount())
4602     {
4603         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4604         return false;
4605     }
4606 
4607     for (int uniformId = 0; uniformId < uniformCount; uniformId++)
4608     {
4609         const GLuint index = uniformIndices[uniformId];
4610 
4611         if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4612         {
4613             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4614             return false;
4615         }
4616     }
4617 
4618     return true;
4619 }
4620 
ValidateGetUniformBlockIndex(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * uniformBlockName)4621 bool ValidateGetUniformBlockIndex(const Context *context,
4622                                   angle::EntryPoint entryPoint,
4623                                   ShaderProgramID program,
4624                                   const GLchar *uniformBlockName)
4625 {
4626     if (context->getClientMajorVersion() < 3)
4627     {
4628         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4629         return false;
4630     }
4631 
4632     Program *programObject = GetValidProgram(context, entryPoint, program);
4633     if (!programObject)
4634     {
4635         return false;
4636     }
4637 
4638     return true;
4639 }
4640 
ValidateGetActiveUniformBlockiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,const GLint * params)4641 bool ValidateGetActiveUniformBlockiv(const Context *context,
4642                                      angle::EntryPoint entryPoint,
4643                                      ShaderProgramID program,
4644                                      UniformBlockIndex uniformBlockIndex,
4645                                      GLenum pname,
4646                                      const GLint *params)
4647 {
4648     return ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex,
4649                                                pname, nullptr);
4650 }
4651 
ValidateGetActiveUniformBlockName(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLsizei bufSize,const GLsizei * length,const GLchar * uniformBlockName)4652 bool ValidateGetActiveUniformBlockName(const Context *context,
4653                                        angle::EntryPoint entryPoint,
4654                                        ShaderProgramID program,
4655                                        UniformBlockIndex uniformBlockIndex,
4656                                        GLsizei bufSize,
4657                                        const GLsizei *length,
4658                                        const GLchar *uniformBlockName)
4659 {
4660     if (context->getClientMajorVersion() < 3)
4661     {
4662         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4663         return false;
4664     }
4665 
4666     Program *programObject = GetValidProgram(context, entryPoint, program);
4667     if (!programObject)
4668     {
4669         return false;
4670     }
4671 
4672     if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
4673     {
4674         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
4675         return false;
4676     }
4677 
4678     return true;
4679 }
4680 
ValidateUniformBlockBinding(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)4681 bool ValidateUniformBlockBinding(const Context *context,
4682                                  angle::EntryPoint entryPoint,
4683                                  ShaderProgramID program,
4684                                  UniformBlockIndex uniformBlockIndex,
4685                                  GLuint uniformBlockBinding)
4686 {
4687     if (context->getClientMajorVersion() < 3)
4688     {
4689         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4690         return false;
4691     }
4692 
4693     if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
4694     {
4695         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4696         return false;
4697     }
4698 
4699     Program *programObject = GetValidProgram(context, entryPoint, program);
4700     if (!programObject)
4701     {
4702         return false;
4703     }
4704 
4705     // if never linked, there won't be any uniform blocks
4706     if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
4707     {
4708         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4709         return false;
4710     }
4711 
4712     return true;
4713 }
4714 
ValidateDrawArraysInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4715 bool ValidateDrawArraysInstanced(const Context *context,
4716                                  angle::EntryPoint entryPoint,
4717                                  PrimitiveMode mode,
4718                                  GLint first,
4719                                  GLsizei count,
4720                                  GLsizei primcount)
4721 {
4722     if (context->getClientMajorVersion() < 3)
4723     {
4724         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4725         return false;
4726     }
4727 
4728     return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount);
4729 }
4730 
ValidateFenceSync(const Context * context,angle::EntryPoint entryPoint,GLenum condition,GLbitfield flags)4731 bool ValidateFenceSync(const Context *context,
4732                        angle::EntryPoint entryPoint,
4733                        GLenum condition,
4734                        GLbitfield flags)
4735 {
4736     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4737     {
4738         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4739         return false;
4740     }
4741 
4742     if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
4743     {
4744         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFenceCondition);
4745         return false;
4746     }
4747 
4748     if (flags != 0)
4749     {
4750         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4751         return false;
4752     }
4753 
4754     return true;
4755 }
4756 
ValidateIsSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked)4757 bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked)
4758 {
4759     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4760     {
4761         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4762         return false;
4763     }
4764 
4765     return true;
4766 }
4767 
ValidateDeleteSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked)4768 bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked)
4769 {
4770     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4771     {
4772         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4773         return false;
4774     }
4775 
4776     if (syncPacked.value != 0 && !context->getSync(syncPacked))
4777     {
4778         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4779         return false;
4780     }
4781 
4782     return true;
4783 }
4784 
ValidateClientWaitSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLbitfield flags,GLuint64 timeout)4785 bool ValidateClientWaitSync(const Context *context,
4786                             angle::EntryPoint entryPoint,
4787                             SyncID syncPacked,
4788                             GLbitfield flags,
4789                             GLuint64 timeout)
4790 {
4791     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4792     {
4793         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4794         return false;
4795     }
4796 
4797     if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
4798     {
4799         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4800         return false;
4801     }
4802 
4803     Sync *clientWaitSync = context->getSync(syncPacked);
4804     if (!clientWaitSync)
4805     {
4806         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4807         return false;
4808     }
4809 
4810     return true;
4811 }
4812 
ValidateWaitSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLbitfield flags,GLuint64 timeout)4813 bool ValidateWaitSync(const Context *context,
4814                       angle::EntryPoint entryPoint,
4815                       SyncID syncPacked,
4816                       GLbitfield flags,
4817                       GLuint64 timeout)
4818 {
4819     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4820     {
4821         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4822         return false;
4823     }
4824 
4825     if (flags != 0)
4826     {
4827         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4828         return false;
4829     }
4830 
4831     if (timeout != GL_TIMEOUT_IGNORED)
4832     {
4833         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTimeout);
4834         return false;
4835     }
4836 
4837     Sync *waitSync = context->getSync(syncPacked);
4838     if (!waitSync)
4839     {
4840         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4841         return false;
4842     }
4843 
4844     return true;
4845 }
4846 
ValidateGetInteger64v(const Context * context,angle::EntryPoint entryPoint,GLenum pname,const GLint64 * params)4847 bool ValidateGetInteger64v(const Context *context,
4848                            angle::EntryPoint entryPoint,
4849                            GLenum pname,
4850                            const GLint64 *params)
4851 {
4852     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4853     {
4854         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4855         return false;
4856     }
4857 
4858     GLenum nativeType      = GL_NONE;
4859     unsigned int numParams = 0;
4860     if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
4861     {
4862         return false;
4863     }
4864 
4865     return true;
4866 }
4867 
ValidateIsSampler(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler)4868 bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler)
4869 {
4870     if (context->getClientMajorVersion() < 3)
4871     {
4872         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4873         return false;
4874     }
4875 
4876     return true;
4877 }
4878 
ValidateBindSampler(const Context * context,angle::EntryPoint entryPoint,GLuint unit,SamplerID sampler)4879 bool ValidateBindSampler(const Context *context,
4880                          angle::EntryPoint entryPoint,
4881                          GLuint unit,
4882                          SamplerID sampler)
4883 {
4884     if (context->getClientMajorVersion() < 3)
4885     {
4886         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4887         return false;
4888     }
4889 
4890     if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
4891     {
4892         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
4893         return false;
4894     }
4895 
4896     if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
4897     {
4898         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCombinedImageUnit);
4899         return false;
4900     }
4901 
4902     return true;
4903 }
4904 
ValidateVertexAttribDivisor(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLuint divisor)4905 bool ValidateVertexAttribDivisor(const Context *context,
4906                                  angle::EntryPoint entryPoint,
4907                                  GLuint index,
4908                                  GLuint divisor)
4909 {
4910     if (context->getClientMajorVersion() < 3)
4911     {
4912         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4913         return false;
4914     }
4915 
4916     return ValidateVertexAttribIndex(context->getPrivateState(),
4917                                      context->getMutableErrorSetForValidation(), entryPoint, index);
4918 }
4919 
ValidateTexStorage2D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)4920 bool ValidateTexStorage2D(const Context *context,
4921                           angle::EntryPoint entryPoint,
4922                           TextureType target,
4923                           GLsizei levels,
4924                           GLenum internalformat,
4925                           GLsizei width,
4926                           GLsizei height)
4927 {
4928     if (context->getClientMajorVersion() < 3)
4929     {
4930         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4931         return false;
4932     }
4933 
4934     if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat,
4935                                            width, height, 1))
4936     {
4937         return false;
4938     }
4939 
4940     return true;
4941 }
4942 
ValidateTexStorage3D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)4943 bool ValidateTexStorage3D(const Context *context,
4944                           angle::EntryPoint entryPoint,
4945                           TextureType target,
4946                           GLsizei levels,
4947                           GLenum internalformat,
4948                           GLsizei width,
4949                           GLsizei height,
4950                           GLsizei depth)
4951 {
4952     if (context->getClientMajorVersion() < 3)
4953     {
4954         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4955         return false;
4956     }
4957 
4958     if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
4959                                            width, height, depth))
4960     {
4961         return false;
4962     }
4963 
4964     return true;
4965 }
4966 
ValidateGetBufferParameteri64v(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,const GLint64 * params)4967 bool ValidateGetBufferParameteri64v(const Context *context,
4968                                     angle::EntryPoint entryPoint,
4969                                     BufferBinding target,
4970                                     GLenum pname,
4971                                     const GLint64 *params)
4972 {
4973     return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
4974 }
4975 
ValidateGetSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)4976 bool ValidateGetSamplerParameterfv(const Context *context,
4977                                    angle::EntryPoint entryPoint,
4978                                    SamplerID sampler,
4979                                    GLenum pname,
4980                                    const GLfloat *params)
4981 {
4982     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4983 }
4984 
ValidateGetSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4985 bool ValidateGetSamplerParameteriv(const Context *context,
4986                                    angle::EntryPoint entryPoint,
4987                                    SamplerID sampler,
4988                                    GLenum pname,
4989                                    const GLint *params)
4990 {
4991     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4992 }
4993 
ValidateGetSamplerParameterIivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4994 bool ValidateGetSamplerParameterIivOES(const Context *context,
4995                                        angle::EntryPoint entryPoint,
4996                                        SamplerID sampler,
4997                                        GLenum pname,
4998                                        const GLint *params)
4999 {
5000     if (context->getClientMajorVersion() < 3)
5001     {
5002         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5003         return false;
5004     }
5005     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
5006 }
5007 
ValidateGetSamplerParameterIuivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLuint * params)5008 bool ValidateGetSamplerParameterIuivOES(const Context *context,
5009                                         angle::EntryPoint entryPoint,
5010                                         SamplerID sampler,
5011                                         GLenum pname,
5012                                         const GLuint *params)
5013 {
5014     if (context->getClientMajorVersion() < 3)
5015     {
5016         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5017         return false;
5018     }
5019     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
5020 }
5021 
ValidateSamplerParameterf(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLfloat param)5022 bool ValidateSamplerParameterf(const Context *context,
5023                                angle::EntryPoint entryPoint,
5024                                SamplerID sampler,
5025                                GLenum pname,
5026                                GLfloat param)
5027 {
5028     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
5029 }
5030 
ValidateSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)5031 bool ValidateSamplerParameterfv(const Context *context,
5032                                 angle::EntryPoint entryPoint,
5033                                 SamplerID sampler,
5034                                 GLenum pname,
5035                                 const GLfloat *params)
5036 {
5037     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5038 }
5039 
ValidateSamplerParameteri(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLint param)5040 bool ValidateSamplerParameteri(const Context *context,
5041                                angle::EntryPoint entryPoint,
5042                                SamplerID sampler,
5043                                GLenum pname,
5044                                GLint param)
5045 {
5046     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
5047 }
5048 
ValidateSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)5049 bool ValidateSamplerParameteriv(const Context *context,
5050                                 angle::EntryPoint entryPoint,
5051                                 SamplerID sampler,
5052                                 GLenum pname,
5053                                 const GLint *params)
5054 {
5055     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5056 }
5057 
ValidateSamplerParameterIivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)5058 bool ValidateSamplerParameterIivOES(const Context *context,
5059                                     angle::EntryPoint entryPoint,
5060                                     SamplerID sampler,
5061                                     GLenum pname,
5062                                     const GLint *params)
5063 {
5064     if (context->getClientMajorVersion() < 3)
5065     {
5066         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5067         return false;
5068     }
5069     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5070 }
5071 
ValidateSamplerParameterIuivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLuint * params)5072 bool ValidateSamplerParameterIuivOES(const Context *context,
5073                                      angle::EntryPoint entryPoint,
5074                                      SamplerID sampler,
5075                                      GLenum pname,
5076                                      const GLuint *params)
5077 {
5078     if (context->getClientMajorVersion() < 3)
5079     {
5080         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5081         return false;
5082     }
5083     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5084 }
5085 
ValidateGetVertexAttribIiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLint * params)5086 bool ValidateGetVertexAttribIiv(const Context *context,
5087                                 angle::EntryPoint entryPoint,
5088                                 GLuint index,
5089                                 GLenum pname,
5090                                 const GLint *params)
5091 {
5092     return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
5093 }
5094 
ValidateGetVertexAttribIuiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLuint * params)5095 bool ValidateGetVertexAttribIuiv(const Context *context,
5096                                  angle::EntryPoint entryPoint,
5097                                  GLuint index,
5098                                  GLenum pname,
5099                                  const GLuint *params)
5100 {
5101     return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
5102 }
5103 
ValidateGetInternalformativ(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLint * params)5104 bool ValidateGetInternalformativ(const Context *context,
5105                                  angle::EntryPoint entryPoint,
5106                                  GLenum target,
5107                                  GLenum internalformat,
5108                                  GLenum pname,
5109                                  GLsizei bufSize,
5110                                  const GLint *params)
5111 {
5112     return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
5113                                            bufSize, nullptr);
5114 }
5115 
ValidateBindFragDataLocationIndexedEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,GLuint index,const char * name)5116 bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
5117                                             angle::EntryPoint entryPoint,
5118                                             ShaderProgramID program,
5119                                             GLuint colorNumber,
5120                                             GLuint index,
5121                                             const char *name)
5122 {
5123     if (!context->getExtensions().blendFuncExtendedEXT)
5124     {
5125         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5126         return false;
5127     }
5128     if (context->getClientMajorVersion() < 3)
5129     {
5130         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5131         return false;
5132     }
5133     if (index > 1)
5134     {
5135         // This error is not explicitly specified but the spec does say that "<index> may be zero or
5136         // one to specify that the color be used as either the first or second color input to the
5137         // blend equation, respectively"
5138         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
5139         return false;
5140     }
5141     if (index == 1)
5142     {
5143         if (colorNumber >= context->getCaps().maxDualSourceDrawBuffers)
5144         {
5145             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
5146                                    kColorNumberGreaterThanMaxDualSourceDrawBuffers);
5147             return false;
5148         }
5149     }
5150     else
5151     {
5152         if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
5153         {
5154             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kColorNumberGreaterThanMaxDrawBuffers);
5155             return false;
5156         }
5157     }
5158     Program *programObject = GetValidProgram(context, entryPoint, program);
5159     if (!programObject)
5160     {
5161         return false;
5162     }
5163     return true;
5164 }
5165 
ValidateBindFragDataLocationEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,const char * name)5166 bool ValidateBindFragDataLocationEXT(const Context *context,
5167                                      angle::EntryPoint entryPoint,
5168                                      ShaderProgramID program,
5169                                      GLuint colorNumber,
5170                                      const char *name)
5171 {
5172     return ValidateBindFragDataLocationIndexedEXT(context, entryPoint, program, colorNumber, 0u,
5173                                                   name);
5174 }
5175 
ValidateGetFragDataIndexEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const char * name)5176 bool ValidateGetFragDataIndexEXT(const Context *context,
5177                                  angle::EntryPoint entryPoint,
5178                                  ShaderProgramID program,
5179                                  const char *name)
5180 {
5181     if (!context->getExtensions().blendFuncExtendedEXT)
5182     {
5183         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5184         return false;
5185     }
5186     if (context->getClientMajorVersion() < 3)
5187     {
5188         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5189         return false;
5190     }
5191     Program *programObject = GetValidProgram(context, entryPoint, program);
5192     if (!programObject)
5193     {
5194         return false;
5195     }
5196     if (!programObject->isLinked())
5197     {
5198         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
5199         return false;
5200     }
5201     return true;
5202 }
5203 
ValidateTexStorage2DMultisampleANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)5204 bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
5205                                           angle::EntryPoint entryPoint,
5206                                           TextureType target,
5207                                           GLsizei samples,
5208                                           GLenum internalFormat,
5209                                           GLsizei width,
5210                                           GLsizei height,
5211                                           GLboolean fixedSampleLocations)
5212 {
5213     if (!context->getExtensions().textureMultisampleANGLE)
5214     {
5215         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
5216         return false;
5217     }
5218 
5219     return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
5220                                                width, height);
5221 }
5222 
ValidateGetTexLevelParameterfvANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLfloat * params)5223 bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
5224                                          angle::EntryPoint entryPoint,
5225                                          TextureTarget target,
5226                                          GLint level,
5227                                          GLenum pname,
5228                                          const GLfloat *params)
5229 {
5230     if (!context->getExtensions().textureMultisampleANGLE &&
5231         !context->getExtensions().getTexLevelParameterANGLE)
5232     {
5233         ANGLE_VALIDATION_ERROR(
5234             GL_INVALID_OPERATION,
5235             kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5236         return false;
5237     }
5238 
5239     return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5240 }
5241 
ValidateGetTexLevelParameterivANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLint * params)5242 bool ValidateGetTexLevelParameterivANGLE(const Context *context,
5243                                          angle::EntryPoint entryPoint,
5244                                          TextureTarget target,
5245                                          GLint level,
5246                                          GLenum pname,
5247                                          const GLint *params)
5248 {
5249     if (!context->getExtensions().textureMultisampleANGLE &&
5250         !context->getExtensions().getTexLevelParameterANGLE)
5251     {
5252         ANGLE_VALIDATION_ERROR(
5253             GL_INVALID_OPERATION,
5254             kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5255         return false;
5256     }
5257 
5258     return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5259 }
5260 
ValidateGetMultisamplefvANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,const GLfloat * val)5261 bool ValidateGetMultisamplefvANGLE(const Context *context,
5262                                    angle::EntryPoint entryPoint,
5263                                    GLenum pname,
5264                                    GLuint index,
5265                                    const GLfloat *val)
5266 {
5267     if (!context->getExtensions().textureMultisampleANGLE)
5268     {
5269         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
5270         return false;
5271     }
5272 
5273     return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
5274 }
5275 
ValidateSampleMaskiANGLE(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint maskNumber,GLbitfield mask)5276 bool ValidateSampleMaskiANGLE(const PrivateState &state,
5277                               ErrorSet *errors,
5278                               angle::EntryPoint entryPoint,
5279                               GLuint maskNumber,
5280                               GLbitfield mask)
5281 {
5282     if (!state.getExtensions().textureMultisampleANGLE)
5283     {
5284         errors->validationError(entryPoint, GL_INVALID_OPERATION,
5285                                 kMultisampleTextureExtensionOrES31Required);
5286         return false;
5287     }
5288 
5289     return ValidateSampleMaskiBase(state, errors, entryPoint, maskNumber, mask);
5290 }
5291 
ValidateDrawBufferIndexIfActivePLS(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint drawBufferIdx,const char * argumentName)5292 bool ValidateDrawBufferIndexIfActivePLS(const PrivateState &state,
5293                                         ErrorSet *errors,
5294                                         angle::EntryPoint entryPoint,
5295                                         GLuint drawBufferIdx,
5296                                         const char *argumentName)
5297 {
5298     int numPLSPlanes = state.getPixelLocalStorageActivePlanes();
5299     if (numPLSPlanes != 0)
5300     {
5301         // INVALID_OPERATION is generated ... if any of the following are true:
5302         //
5303         //   <drawBufferIdx> >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
5304         //   <drawBufferIdx> >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
5305         //                       ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE)
5306         //
5307         if (drawBufferIdx >= state.getCaps().maxColorAttachmentsWithActivePixelLocalStorage)
5308         {
5309             errors->validationErrorF(entryPoint, GL_INVALID_OPERATION,
5310                                      kPLSDrawBufferExceedsAttachmentLimit, argumentName);
5311             return false;
5312         }
5313         if (drawBufferIdx >=
5314             state.getCaps().maxCombinedDrawBuffersAndPixelLocalStoragePlanes - numPLSPlanes)
5315         {
5316             errors->validationErrorF(entryPoint, GL_INVALID_OPERATION,
5317                                      kPLSDrawBufferExceedsCombinedAttachmentLimit, argumentName);
5318             return false;
5319         }
5320     }
5321     return true;
5322 }
5323 }  // namespace gl
5324