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