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