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