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