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