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