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