• 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     //angle CVE-2022-0975
2978     if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
2979     {
2980         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
2981         return false;
2982     }
2983 
2984     return true;
2985 }
2986 
ValidateGetBufferPointerv(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,void * const * params)2987 bool ValidateGetBufferPointerv(const Context *context,
2988                                angle::EntryPoint entryPoint,
2989                                BufferBinding target,
2990                                GLenum pname,
2991                                void *const *params)
2992 {
2993     if (context->getClientMajorVersion() < 3)
2994     {
2995         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
2996         return false;
2997     }
2998 
2999     return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
3000 }
3001 
ValidateGetBufferPointervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)3002 bool ValidateGetBufferPointervRobustANGLE(const Context *context,
3003                                           angle::EntryPoint entryPoint,
3004                                           BufferBinding target,
3005                                           GLenum pname,
3006                                           GLsizei bufSize,
3007                                           const GLsizei *length,
3008                                           void *const *params)
3009 {
3010     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3011     {
3012         return false;
3013     }
3014 
3015     GLsizei numParams = 0;
3016 
3017     if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES)
3018     {
3019         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3020         return false;
3021     }
3022 
3023     if (!ValidateGetBufferPointervBase(context, entryPoint, target, pname, &numParams, params))
3024     {
3025         return false;
3026     }
3027 
3028     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3029     {
3030         return false;
3031     }
3032 
3033     SetRobustLengthParam(length, numParams);
3034 
3035     return true;
3036 }
3037 
ValidateUnmapBuffer(const Context * context,angle::EntryPoint entryPoint,BufferBinding target)3038 bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target)
3039 {
3040     if (context->getClientMajorVersion() < 3)
3041     {
3042         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3043         return false;
3044     }
3045 
3046     return ValidateUnmapBufferBase(context, entryPoint, target);
3047 }
3048 
ValidateMapBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3049 bool ValidateMapBufferRange(const Context *context,
3050                             angle::EntryPoint entryPoint,
3051                             BufferBinding target,
3052                             GLintptr offset,
3053                             GLsizeiptr length,
3054                             GLbitfield access)
3055 {
3056     if (context->getClientMajorVersion() < 3)
3057     {
3058         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3059         return false;
3060     }
3061 
3062     return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
3063 }
3064 
ValidateFlushMappedBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length)3065 bool ValidateFlushMappedBufferRange(const Context *context,
3066                                     angle::EntryPoint entryPoint,
3067                                     BufferBinding target,
3068                                     GLintptr offset,
3069                                     GLsizeiptr length)
3070 {
3071     if (context->getClientMajorVersion() < 3)
3072     {
3073         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3074         return false;
3075     }
3076 
3077     return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
3078 }
3079 
ValidateIndexedStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,GLsizei * length)3080 bool ValidateIndexedStateQuery(const Context *context,
3081                                angle::EntryPoint entryPoint,
3082                                GLenum pname,
3083                                GLuint index,
3084                                GLsizei *length)
3085 {
3086     if (length)
3087     {
3088         *length = 0;
3089     }
3090 
3091     GLenum nativeType;
3092     unsigned int numParams;
3093     if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
3094     {
3095         context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
3096         return false;
3097     }
3098 
3099     const Caps &caps = context->getCaps();
3100     switch (pname)
3101     {
3102         case GL_BLEND_SRC_RGB:
3103         case GL_BLEND_SRC_ALPHA:
3104         case GL_BLEND_DST_RGB:
3105         case GL_BLEND_DST_ALPHA:
3106         case GL_BLEND_EQUATION_RGB:
3107         case GL_BLEND_EQUATION_ALPHA:
3108         case GL_COLOR_WRITEMASK:
3109             if (!context->getExtensions().drawBuffersIndexedAny())
3110             {
3111                 context->validationError(entryPoint, GL_INVALID_ENUM,
3112                                          kDrawBuffersIndexedExtensionNotAvailable);
3113                 return false;
3114             }
3115             if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
3116             {
3117                 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
3118                 return false;
3119             }
3120             break;
3121         case GL_TRANSFORM_FEEDBACK_BUFFER_START:
3122         case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
3123         case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3124             if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
3125             {
3126                 context->validationError(entryPoint, GL_INVALID_VALUE,
3127                                          kIndexExceedsMaxTransformFeedbackAttribs);
3128                 return false;
3129             }
3130             break;
3131 
3132         case GL_UNIFORM_BUFFER_START:
3133         case GL_UNIFORM_BUFFER_SIZE:
3134         case GL_UNIFORM_BUFFER_BINDING:
3135             if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
3136             {
3137                 context->validationError(entryPoint, GL_INVALID_VALUE,
3138                                          kIndexExceedsMaxUniformBufferBindings);
3139                 return false;
3140             }
3141             break;
3142 
3143         case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
3144         case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
3145             if (index >= 3u)
3146             {
3147                 context->validationError(entryPoint, GL_INVALID_VALUE,
3148                                          kIndexExceedsMaxWorkgroupDimensions);
3149                 return false;
3150             }
3151             break;
3152 
3153         case GL_ATOMIC_COUNTER_BUFFER_START:
3154         case GL_ATOMIC_COUNTER_BUFFER_SIZE:
3155         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3156             if (context->getClientVersion() < ES_3_1)
3157             {
3158                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
3159                 return false;
3160             }
3161             if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
3162             {
3163                 context->validationError(entryPoint, GL_INVALID_VALUE,
3164                                          kIndexExceedsMaxAtomicCounterBufferBindings);
3165                 return false;
3166             }
3167             break;
3168 
3169         case GL_SHADER_STORAGE_BUFFER_START:
3170         case GL_SHADER_STORAGE_BUFFER_SIZE:
3171         case GL_SHADER_STORAGE_BUFFER_BINDING:
3172             if (context->getClientVersion() < ES_3_1)
3173             {
3174                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
3175                 return false;
3176             }
3177             if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
3178             {
3179                 context->validationError(entryPoint, GL_INVALID_VALUE,
3180                                          kExceedsMaxShaderStorageBufferBindings);
3181                 return false;
3182             }
3183             break;
3184 
3185         case GL_VERTEX_BINDING_BUFFER:
3186         case GL_VERTEX_BINDING_DIVISOR:
3187         case GL_VERTEX_BINDING_OFFSET:
3188         case GL_VERTEX_BINDING_STRIDE:
3189             if (context->getClientVersion() < ES_3_1)
3190             {
3191                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
3192                 return false;
3193             }
3194             if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3195             {
3196                 context->validationError(entryPoint, GL_INVALID_VALUE,
3197                                          kExceedsMaxVertexAttribBindings);
3198                 return false;
3199             }
3200             break;
3201         case GL_SAMPLE_MASK_VALUE:
3202             if (context->getClientVersion() < ES_3_1)
3203             {
3204                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
3205                 return false;
3206             }
3207             if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
3208             {
3209                 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
3210                 return false;
3211             }
3212             break;
3213         case GL_IMAGE_BINDING_NAME:
3214         case GL_IMAGE_BINDING_LEVEL:
3215         case GL_IMAGE_BINDING_LAYERED:
3216         case GL_IMAGE_BINDING_LAYER:
3217         case GL_IMAGE_BINDING_ACCESS:
3218         case GL_IMAGE_BINDING_FORMAT:
3219             if (context->getClientVersion() < ES_3_1)
3220             {
3221                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
3222                 return false;
3223             }
3224             if (index >= static_cast<GLuint>(caps.maxImageUnits))
3225             {
3226                 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxImageUnits);
3227                 return false;
3228             }
3229             break;
3230         default:
3231             context->validationError(entryPoint, GL_INVALID_ENUM, kEnumNotSupported);
3232             return false;
3233     }
3234 
3235     if (length)
3236     {
3237         if (pname == GL_COLOR_WRITEMASK)
3238         {
3239             *length = 4;
3240         }
3241         else
3242         {
3243             *length = 1;
3244         }
3245     }
3246 
3247     return true;
3248 }
3249 
ValidateGetIntegeri_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint * data)3250 bool ValidateGetIntegeri_v(const Context *context,
3251                            angle::EntryPoint entryPoint,
3252                            GLenum target,
3253                            GLuint index,
3254                            const GLint *data)
3255 {
3256     if (context->getClientVersion() < ES_3_0)
3257     {
3258         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3259         return false;
3260     }
3261     return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3262 }
3263 
ValidateGetIntegeri_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint * data)3264 bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
3265                                       angle::EntryPoint entryPoint,
3266                                       GLenum target,
3267                                       GLuint index,
3268                                       GLsizei bufSize,
3269                                       const GLsizei *length,
3270                                       const GLint *data)
3271 {
3272     if (context->getClientVersion() < ES_3_0)
3273     {
3274         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3275         return false;
3276     }
3277 
3278     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3279     {
3280         return false;
3281     }
3282 
3283     GLsizei numParams = 0;
3284 
3285     if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3286     {
3287         return false;
3288     }
3289 
3290     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3291     {
3292         return false;
3293     }
3294 
3295     SetRobustLengthParam(length, numParams);
3296 
3297     return true;
3298 }
3299 
ValidateGetInteger64i_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint64 * data)3300 bool ValidateGetInteger64i_v(const Context *context,
3301                              angle::EntryPoint entryPoint,
3302                              GLenum target,
3303                              GLuint index,
3304                              const GLint64 *data)
3305 {
3306     if (context->getClientVersion() < ES_3_0)
3307     {
3308         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3309         return false;
3310     }
3311     return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3312 }
3313 
ValidateGetInteger64i_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint64 * data)3314 bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
3315                                         angle::EntryPoint entryPoint,
3316                                         GLenum target,
3317                                         GLuint index,
3318                                         GLsizei bufSize,
3319                                         const GLsizei *length,
3320                                         const GLint64 *data)
3321 {
3322     if (context->getClientVersion() < ES_3_0)
3323     {
3324         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3325         return false;
3326     }
3327 
3328     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3329     {
3330         return false;
3331     }
3332 
3333     GLsizei numParams = 0;
3334 
3335     if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3336     {
3337         return false;
3338     }
3339 
3340     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3341     {
3342         return false;
3343     }
3344 
3345     SetRobustLengthParam(length, numParams);
3346 
3347     return true;
3348 }
3349 
ValidateCopyBufferSubData(const Context * context,angle::EntryPoint entryPoint,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)3350 bool ValidateCopyBufferSubData(const Context *context,
3351                                angle::EntryPoint entryPoint,
3352                                BufferBinding readTarget,
3353                                BufferBinding writeTarget,
3354                                GLintptr readOffset,
3355                                GLintptr writeOffset,
3356                                GLsizeiptr size)
3357 {
3358     if (context->getClientMajorVersion() < 3)
3359     {
3360         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3361         return false;
3362     }
3363 
3364     if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
3365     {
3366         context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
3367         return false;
3368     }
3369 
3370     Buffer *readBuffer  = context->getState().getTargetBuffer(readTarget);
3371     Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
3372 
3373     if (!readBuffer || !writeBuffer)
3374     {
3375         context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
3376         return false;
3377     }
3378 
3379     // EXT_buffer_storage allows persistently mapped buffers to be updated via glCopyBufferSubData
3380     bool isReadPersistent  = (readBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3381     bool isWritePersistent = (writeBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3382 
3383     // Verify that readBuffer and writeBuffer are not currently mapped unless persistent
3384     if ((readBuffer->isMapped() && !isReadPersistent) ||
3385         (writeBuffer->isMapped() && !isWritePersistent))
3386     {
3387         context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
3388         return false;
3389     }
3390 
3391     if (readBuffer->hasWebGLXFBBindingConflict(context->isWebGL()) ||
3392         writeBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
3393     {
3394         context->validationError(entryPoint, GL_INVALID_OPERATION,
3395                                  kBufferBoundForTransformFeedback);
3396         return false;
3397     }
3398 
3399     CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
3400     CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
3401     CheckedNumeric<GLintptr> checkedSize(size);
3402 
3403     auto checkedReadSum  = checkedReadOffset + checkedSize;
3404     auto checkedWriteSum = checkedWriteOffset + checkedSize;
3405 
3406     if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
3407         !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
3408         !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
3409     {
3410         context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
3411         return false;
3412     }
3413 
3414     if (readOffset < 0 || writeOffset < 0)
3415     {
3416         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
3417         return false;
3418     }
3419 
3420     if (size < 0)
3421     {
3422         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
3423         return false;
3424     }
3425 
3426     if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
3427         checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
3428     {
3429         context->validationError(entryPoint, GL_INVALID_VALUE, kBufferOffsetOverflow);
3430         return false;
3431     }
3432 
3433     if (readBuffer == writeBuffer)
3434     {
3435         auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
3436         if (!checkedOffsetDiff.IsValid())
3437         {
3438             // This shold not be possible.
3439             UNREACHABLE();
3440             context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
3441             return false;
3442         }
3443 
3444         if (checkedOffsetDiff.ValueOrDie() < size)
3445         {
3446             context->validationError(entryPoint, GL_INVALID_VALUE, kCopyAlias);
3447             return false;
3448         }
3449     }
3450 
3451     return true;
3452 }
3453 
ValidateGetStringi(const Context * context,angle::EntryPoint entryPoint,GLenum name,GLuint index)3454 bool ValidateGetStringi(const Context *context,
3455                         angle::EntryPoint entryPoint,
3456                         GLenum name,
3457                         GLuint index)
3458 {
3459     if (context->getClientMajorVersion() < 3)
3460     {
3461         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3462         return false;
3463     }
3464 
3465     switch (name)
3466     {
3467         case GL_EXTENSIONS:
3468             if (index >= context->getExtensionStringCount())
3469             {
3470                 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsNumExtensions);
3471                 return false;
3472             }
3473             break;
3474 
3475         case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3476             if (!context->getExtensions().requestExtensionANGLE)
3477             {
3478                 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
3479                 return false;
3480             }
3481             if (index >= context->getRequestableExtensionStringCount())
3482             {
3483                 context->validationError(entryPoint, GL_INVALID_VALUE,
3484                                          kExceedsNumRequestableExtensions);
3485                 return false;
3486             }
3487             break;
3488 
3489         default:
3490             context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
3491             return false;
3492     }
3493 
3494     return true;
3495 }
3496 
ValidateRenderbufferStorageMultisample(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3497 bool ValidateRenderbufferStorageMultisample(const Context *context,
3498                                             angle::EntryPoint entryPoint,
3499                                             GLenum target,
3500                                             GLsizei samples,
3501                                             GLenum internalformat,
3502                                             GLsizei width,
3503                                             GLsizei height)
3504 {
3505     if (context->getClientMajorVersion() < 3)
3506     {
3507         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3508         return false;
3509     }
3510 
3511     if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
3512                                                    internalformat, width, height))
3513     {
3514         return false;
3515     }
3516 
3517     // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
3518     // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
3519     // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
3520     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
3521     if (formatInfo.isInt())
3522     {
3523         if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
3524             samples > context->getCaps().maxIntegerSamples)
3525         {
3526             context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
3527             return false;
3528         }
3529     }
3530 
3531     // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
3532     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3533     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3534     {
3535         context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
3536         return false;
3537     }
3538 
3539     return true;
3540 }
3541 
ValidateVertexAttribIPointer(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)3542 bool ValidateVertexAttribIPointer(const Context *context,
3543                                   angle::EntryPoint entryPoint,
3544                                   GLuint index,
3545                                   GLint size,
3546                                   VertexAttribType type,
3547                                   GLsizei stride,
3548                                   const void *pointer)
3549 {
3550     if (context->getClientMajorVersion() < 3)
3551     {
3552         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3553         return false;
3554     }
3555 
3556     if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type))
3557     {
3558         return false;
3559     }
3560 
3561     if (stride < 0)
3562     {
3563         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeStride);
3564         return false;
3565     }
3566 
3567     const Caps &caps = context->getCaps();
3568     if (context->getClientVersion() >= ES_3_1)
3569     {
3570         if (stride > caps.maxVertexAttribStride)
3571         {
3572             context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
3573             return false;
3574         }
3575 
3576         // [OpenGL ES 3.1] Section 10.3.1 page 245:
3577         // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3578         // validation should be inherited.
3579         if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3580         {
3581             context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3582             return false;
3583         }
3584     }
3585 
3586     // [OpenGL ES 3.0.2] Section 2.8 page 24:
3587     // An INVALID_OPERATION error is generated when a non-zero vertex array object
3588     // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3589     // and the pointer argument is not NULL.
3590     if (context->getState().getVertexArrayId().value != 0 &&
3591         context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
3592     {
3593         context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray);
3594         return false;
3595     }
3596 
3597     if (context->getExtensions().webglCompatibilityANGLE)
3598     {
3599         if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, false, stride, pointer,
3600                                               true))
3601         {
3602             return false;
3603         }
3604     }
3605 
3606     return true;
3607 }
3608 
ValidateGetSynciv(const Context * context,angle::EntryPoint entryPoint,GLsync sync,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * values)3609 bool ValidateGetSynciv(const Context *context,
3610                        angle::EntryPoint entryPoint,
3611                        GLsync sync,
3612                        GLenum pname,
3613                        GLsizei bufSize,
3614                        const GLsizei *length,
3615                        const GLint *values)
3616 {
3617     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
3618     {
3619         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3620         return false;
3621     }
3622 
3623     if (bufSize < 0)
3624     {
3625         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
3626         return false;
3627     }
3628 
3629     if (context->isContextLost())
3630     {
3631         context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
3632 
3633         if (pname == GL_SYNC_STATUS)
3634         {
3635             // Generate an error but still return true, the context still needs to return a
3636             // value in this case.
3637             return true;
3638         }
3639         else
3640         {
3641             return false;
3642         }
3643     }
3644 
3645     Sync *syncObject = context->getSync(sync);
3646     if (!syncObject)
3647     {
3648         context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
3649         return false;
3650     }
3651 
3652     switch (pname)
3653     {
3654         case GL_OBJECT_TYPE:
3655         case GL_SYNC_CONDITION:
3656         case GL_SYNC_FLAGS:
3657         case GL_SYNC_STATUS:
3658             break;
3659 
3660         default:
3661             context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
3662             return false;
3663     }
3664 
3665     return true;
3666 }
3667 
ValidateDrawElementsInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei instanceCount)3668 bool ValidateDrawElementsInstanced(const Context *context,
3669                                    angle::EntryPoint entryPoint,
3670                                    PrimitiveMode mode,
3671                                    GLsizei count,
3672                                    DrawElementsType type,
3673                                    const void *indices,
3674                                    GLsizei instanceCount)
3675 {
3676     if (context->getClientMajorVersion() < 3)
3677     {
3678         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
3679         return false;
3680     }
3681 
3682     return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3683                                              instanceCount);
3684 }
3685 
ValidateMultiDrawArraysInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)3686 bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
3687                                            angle::EntryPoint entryPoint,
3688                                            PrimitiveMode mode,
3689                                            const GLint *firsts,
3690                                            const GLsizei *counts,
3691                                            const GLsizei *instanceCounts,
3692                                            GLsizei drawcount)
3693 {
3694     if (!context->getExtensions().multiDrawANGLE)
3695     {
3696         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3697         return false;
3698     }
3699     if (context->getClientMajorVersion() < 3)
3700     {
3701         if (!context->getExtensions().instancedArraysAny())
3702         {
3703             context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3704             return false;
3705         }
3706         if (!ValidateDrawInstancedANGLE(context, entryPoint))
3707         {
3708             return false;
3709         }
3710     }
3711     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3712     {
3713         if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID],
3714                                              counts[drawID], instanceCounts[drawID]))
3715         {
3716             return false;
3717         }
3718     }
3719     return true;
3720 }
3721 
ValidateMultiDrawElementsInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)3722 bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
3723                                              angle::EntryPoint entryPoint,
3724                                              PrimitiveMode mode,
3725                                              const GLsizei *counts,
3726                                              DrawElementsType type,
3727                                              const GLvoid *const *indices,
3728                                              const GLsizei *instanceCounts,
3729                                              GLsizei drawcount)
3730 {
3731     if (!context->getExtensions().multiDrawANGLE)
3732     {
3733         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3734         return false;
3735     }
3736     if (context->getClientMajorVersion() < 3)
3737     {
3738         if (!context->getExtensions().instancedArraysAny())
3739         {
3740             context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3741             return false;
3742         }
3743         if (!ValidateDrawInstancedANGLE(context, entryPoint))
3744         {
3745             return false;
3746         }
3747     }
3748     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3749     {
3750         if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type,
3751                                                indices[drawID], instanceCounts[drawID]))
3752         {
3753             return false;
3754         }
3755     }
3756     return true;
3757 }
3758 
ValidateDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)3759 bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3760                                                   angle::EntryPoint entryPoint,
3761                                                   PrimitiveMode mode,
3762                                                   GLint first,
3763                                                   GLsizei count,
3764                                                   GLsizei instanceCount,
3765                                                   GLuint baseInstance)
3766 {
3767     if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3768     {
3769         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3770         return false;
3771     }
3772     if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount))
3773     {
3774         return false;
3775     }
3776     return true;
3777 }
3778 
ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const GLvoid * indices,GLsizei instanceCounts,GLint baseVertex,GLuint baseInstance)3779 bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3780                                                               angle::EntryPoint entryPoint,
3781                                                               PrimitiveMode mode,
3782                                                               GLsizei count,
3783                                                               DrawElementsType type,
3784                                                               const GLvoid *indices,
3785                                                               GLsizei instanceCounts,
3786                                                               GLint baseVertex,
3787                                                               GLuint baseInstance)
3788 {
3789     if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3790     {
3791         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3792         return false;
3793     }
3794     if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3795                                            instanceCounts))
3796     {
3797         return false;
3798     }
3799     return true;
3800 }
3801 
ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode modePacked,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)3802 bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3803                                                        angle::EntryPoint entryPoint,
3804                                                        PrimitiveMode modePacked,
3805                                                        const GLint *firsts,
3806                                                        const GLsizei *counts,
3807                                                        const GLsizei *instanceCounts,
3808                                                        const GLuint *baseInstances,
3809                                                        GLsizei drawcount)
3810 {
3811     if (!context->getExtensions().multiDrawANGLE)
3812     {
3813         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3814         return false;
3815     }
3816     if (drawcount < 0)
3817     {
3818         return false;
3819     }
3820     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3821     {
3822         if (!ValidateDrawArraysInstancedBase(context, entryPoint, modePacked, firsts[drawID],
3823                                              counts[drawID], instanceCounts[drawID]))
3824         {
3825             return false;
3826         }
3827     }
3828     return true;
3829 }
3830 
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)3831 bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3832                                                                    angle::EntryPoint entryPoint,
3833                                                                    PrimitiveMode modePacked,
3834                                                                    const GLsizei *counts,
3835                                                                    DrawElementsType typePacked,
3836                                                                    const GLvoid *const *indices,
3837                                                                    const GLsizei *instanceCounts,
3838                                                                    const GLint *baseVertices,
3839                                                                    const GLuint *baseInstances,
3840                                                                    GLsizei drawcount)
3841 {
3842     if (!context->getExtensions().multiDrawANGLE)
3843     {
3844         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
3845         return false;
3846     }
3847     if (drawcount < 0)
3848     {
3849         return false;
3850     }
3851     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3852     {
3853         if (!ValidateDrawElementsInstancedBase(context, entryPoint, modePacked, counts[drawID],
3854                                                typePacked, indices[drawID], instanceCounts[drawID]))
3855         {
3856             return false;
3857         }
3858     }
3859     return true;
3860 }
3861 
ValidateFramebufferTextureMultiviewOVR(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint baseViewIndex,GLsizei numViews)3862 bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
3863                                             angle::EntryPoint entryPoint,
3864                                             GLenum target,
3865                                             GLenum attachment,
3866                                             TextureID texture,
3867                                             GLint level,
3868                                             GLint baseViewIndex,
3869                                             GLsizei numViews)
3870 {
3871     if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment,
3872                                                       texture, level, numViews))
3873     {
3874         return false;
3875     }
3876 
3877     if (texture.value != 0)
3878     {
3879         if (baseViewIndex < 0)
3880         {
3881             context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBaseViewIndex);
3882             return false;
3883         }
3884 
3885         Texture *tex = context->getTexture(texture);
3886         ASSERT(tex);
3887 
3888         switch (tex->getType())
3889         {
3890             case TextureType::_2DArray:
3891             case TextureType::_2DMultisampleArray:
3892             {
3893                 if (tex->getType() == TextureType::_2DMultisampleArray)
3894                 {
3895                     if (!context->getExtensions().multiviewMultisampleANGLE)
3896                     {
3897                         context->validationError(entryPoint, GL_INVALID_OPERATION,
3898                                                  kInvalidTextureType);
3899                         return false;
3900                     }
3901                 }
3902 
3903                 const Caps &caps = context->getCaps();
3904                 if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
3905                 {
3906                     context->validationError(entryPoint, GL_INVALID_VALUE,
3907                                              kViewsExceedMaxArrayLayers);
3908                     return false;
3909                 }
3910 
3911                 break;
3912             }
3913             default:
3914                 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType);
3915                 return false;
3916         }
3917 
3918         if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, entryPoint, tex, level))
3919         {
3920             return false;
3921         }
3922     }
3923 
3924     return true;
3925 }
3926 
ValidateUniform1ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0)3927 bool ValidateUniform1ui(const Context *context,
3928                         angle::EntryPoint entryPoint,
3929                         UniformLocation location,
3930                         GLuint v0)
3931 {
3932     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1);
3933 }
3934 
ValidateUniform2ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1)3935 bool ValidateUniform2ui(const Context *context,
3936                         angle::EntryPoint entryPoint,
3937                         UniformLocation location,
3938                         GLuint v0,
3939                         GLuint v1)
3940 {
3941     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1);
3942 }
3943 
ValidateUniform3ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2)3944 bool ValidateUniform3ui(const Context *context,
3945                         angle::EntryPoint entryPoint,
3946                         UniformLocation location,
3947                         GLuint v0,
3948                         GLuint v1,
3949                         GLuint v2)
3950 {
3951     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1);
3952 }
3953 
ValidateUniform4ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)3954 bool ValidateUniform4ui(const Context *context,
3955                         angle::EntryPoint entryPoint,
3956                         UniformLocation location,
3957                         GLuint v0,
3958                         GLuint v1,
3959                         GLuint v2,
3960                         GLuint v3)
3961 {
3962     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1);
3963 }
3964 
ValidateUniform1uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)3965 bool ValidateUniform1uiv(const Context *context,
3966                          angle::EntryPoint entryPoint,
3967                          UniformLocation location,
3968                          GLsizei count,
3969                          const GLuint *value)
3970 {
3971     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count);
3972 }
3973 
ValidateUniform2uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)3974 bool ValidateUniform2uiv(const Context *context,
3975                          angle::EntryPoint entryPoint,
3976                          UniformLocation location,
3977                          GLsizei count,
3978                          const GLuint *value)
3979 {
3980     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count);
3981 }
3982 
ValidateUniform3uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)3983 bool ValidateUniform3uiv(const Context *context,
3984                          angle::EntryPoint entryPoint,
3985                          UniformLocation location,
3986                          GLsizei count,
3987                          const GLuint *value)
3988 {
3989     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count);
3990 }
3991 
ValidateUniform4uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)3992 bool ValidateUniform4uiv(const Context *context,
3993                          angle::EntryPoint entryPoint,
3994                          UniformLocation location,
3995                          GLsizei count,
3996                          const GLuint *value)
3997 {
3998     return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count);
3999 }
4000 
ValidateIsQuery(const Context * context,angle::EntryPoint entryPoint,QueryID id)4001 bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id)
4002 {
4003     if (context->getClientMajorVersion() < 3)
4004     {
4005         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4006         return false;
4007     }
4008 
4009     return true;
4010 }
4011 
ValidateUniformMatrix2x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4012 bool ValidateUniformMatrix2x3fv(const Context *context,
4013                                 angle::EntryPoint entryPoint,
4014                                 UniformLocation location,
4015                                 GLsizei count,
4016                                 GLboolean transpose,
4017                                 const GLfloat *value)
4018 {
4019     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count,
4020                                     transpose);
4021 }
4022 
ValidateUniformMatrix3x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4023 bool ValidateUniformMatrix3x2fv(const Context *context,
4024                                 angle::EntryPoint entryPoint,
4025                                 UniformLocation location,
4026                                 GLsizei count,
4027                                 GLboolean transpose,
4028                                 const GLfloat *value)
4029 {
4030     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count,
4031                                     transpose);
4032 }
4033 
ValidateUniformMatrix2x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4034 bool ValidateUniformMatrix2x4fv(const Context *context,
4035                                 angle::EntryPoint entryPoint,
4036                                 UniformLocation location,
4037                                 GLsizei count,
4038                                 GLboolean transpose,
4039                                 const GLfloat *value)
4040 {
4041     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count,
4042                                     transpose);
4043 }
4044 
ValidateUniformMatrix4x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4045 bool ValidateUniformMatrix4x2fv(const Context *context,
4046                                 angle::EntryPoint entryPoint,
4047                                 UniformLocation location,
4048                                 GLsizei count,
4049                                 GLboolean transpose,
4050                                 const GLfloat *value)
4051 {
4052     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count,
4053                                     transpose);
4054 }
4055 
ValidateUniformMatrix3x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4056 bool ValidateUniformMatrix3x4fv(const Context *context,
4057                                 angle::EntryPoint entryPoint,
4058                                 UniformLocation location,
4059                                 GLsizei count,
4060                                 GLboolean transpose,
4061                                 const GLfloat *value)
4062 {
4063     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count,
4064                                     transpose);
4065 }
4066 
ValidateUniformMatrix4x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4067 bool ValidateUniformMatrix4x3fv(const Context *context,
4068                                 angle::EntryPoint entryPoint,
4069                                 UniformLocation location,
4070                                 GLsizei count,
4071                                 GLboolean transpose,
4072                                 const GLfloat *value)
4073 {
4074     return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count,
4075                                     transpose);
4076 }
4077 
ValidateEndTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4078 bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4079 {
4080     if (context->getClientMajorVersion() < 3)
4081     {
4082         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4083         return false;
4084     }
4085 
4086     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4087     ASSERT(transformFeedback != nullptr);
4088 
4089     if (!transformFeedback->isActive())
4090     {
4091         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4092         return false;
4093     }
4094 
4095     return true;
4096 }
4097 
ValidateTransformFeedbackVaryings(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)4098 bool ValidateTransformFeedbackVaryings(const Context *context,
4099                                        angle::EntryPoint entryPoint,
4100                                        ShaderProgramID program,
4101                                        GLsizei count,
4102                                        const GLchar *const *varyings,
4103                                        GLenum bufferMode)
4104 {
4105     if (context->getClientMajorVersion() < 3)
4106     {
4107         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4108         return false;
4109     }
4110 
4111     if (count < 0)
4112     {
4113         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
4114         return false;
4115     }
4116 
4117     switch (bufferMode)
4118     {
4119         case GL_INTERLEAVED_ATTRIBS:
4120             break;
4121         case GL_SEPARATE_ATTRIBS:
4122         {
4123             const Caps &caps = context->getCaps();
4124             if (count > caps.maxTransformFeedbackSeparateAttributes)
4125             {
4126                 context->validationError(entryPoint, GL_INVALID_VALUE,
4127                                          kInvalidTransformFeedbackAttribsCount);
4128                 return false;
4129             }
4130             break;
4131         }
4132         default:
4133             context->validationError(entryPoint, GL_INVALID_ENUM, kEnumNotSupported);
4134             return false;
4135     }
4136 
4137     Program *programObject = GetValidProgram(context, entryPoint, program);
4138     if (!programObject)
4139     {
4140         return false;
4141     }
4142 
4143     return true;
4144 }
4145 
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)4146 bool ValidateGetTransformFeedbackVarying(const Context *context,
4147                                          angle::EntryPoint entryPoint,
4148                                          ShaderProgramID program,
4149                                          GLuint index,
4150                                          GLsizei bufSize,
4151                                          const GLsizei *length,
4152                                          const GLsizei *size,
4153                                          const GLenum *type,
4154                                          const GLchar *name)
4155 {
4156     if (context->getClientMajorVersion() < 3)
4157     {
4158         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4159         return false;
4160     }
4161 
4162     if (bufSize < 0)
4163     {
4164         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
4165         return false;
4166     }
4167 
4168     Program *programObject = GetValidProgram(context, entryPoint, program);
4169     if (!programObject)
4170     {
4171         return false;
4172     }
4173 
4174     if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
4175     {
4176         context->validationError(entryPoint, GL_INVALID_VALUE,
4177                                  kTransformFeedbackVaryingIndexOutOfRange);
4178         return false;
4179     }
4180 
4181     return true;
4182 }
4183 
ValidateBindTransformFeedback(const Context * context,angle::EntryPoint entryPoint,GLenum target,TransformFeedbackID id)4184 bool ValidateBindTransformFeedback(const Context *context,
4185                                    angle::EntryPoint entryPoint,
4186                                    GLenum target,
4187                                    TransformFeedbackID id)
4188 {
4189     if (context->getClientMajorVersion() < 3)
4190     {
4191         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4192         return false;
4193     }
4194 
4195     switch (target)
4196     {
4197         case GL_TRANSFORM_FEEDBACK:
4198         {
4199             // Cannot bind a transform feedback object if the current one is started and not
4200             // paused (3.0.2 pg 85 section 2.14.1)
4201             if (context->getState().isTransformFeedbackActiveUnpaused())
4202             {
4203                 context->validationError(entryPoint, GL_INVALID_OPERATION,
4204                                          kTransformFeedbackNotPaused);
4205                 return false;
4206             }
4207 
4208             // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
4209             // 2.14.1)
4210             if (!context->isTransformFeedbackGenerated(id))
4211             {
4212                 context->validationError(entryPoint, GL_INVALID_OPERATION,
4213                                          kTransformFeedbackDoesNotExist);
4214                 return false;
4215             }
4216         }
4217         break;
4218 
4219         default:
4220             context->validationError(entryPoint, GL_INVALID_ENUM, kEnumNotSupported);
4221             return false;
4222     }
4223 
4224     return true;
4225 }
4226 
ValidateIsTransformFeedback(const Context * context,angle::EntryPoint entryPoint,TransformFeedbackID id)4227 bool ValidateIsTransformFeedback(const Context *context,
4228                                  angle::EntryPoint entryPoint,
4229                                  TransformFeedbackID id)
4230 {
4231     if (context->getClientMajorVersion() < 3)
4232     {
4233         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4234         return false;
4235     }
4236 
4237     return true;
4238 }
4239 
ValidatePauseTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4240 bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4241 {
4242     if (context->getClientMajorVersion() < 3)
4243     {
4244         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4245         return false;
4246     }
4247 
4248     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4249     ASSERT(transformFeedback != nullptr);
4250 
4251     // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
4252     if (!transformFeedback->isActive())
4253     {
4254         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4255         return false;
4256     }
4257 
4258     if (transformFeedback->isPaused())
4259     {
4260         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackPaused);
4261         return false;
4262     }
4263 
4264     return true;
4265 }
4266 
ValidateResumeTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4267 bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4268 {
4269     if (context->getClientMajorVersion() < 3)
4270     {
4271         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4272         return false;
4273     }
4274 
4275     TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4276     ASSERT(transformFeedback != nullptr);
4277 
4278     // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
4279     if (!transformFeedback->isActive())
4280     {
4281         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4282         return false;
4283     }
4284 
4285     if (!transformFeedback->isPaused())
4286     {
4287         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
4288         return false;
4289     }
4290 
4291     //angle CVE-2022-1477
4292     if (!ValidateProgramExecutableXFBBuffersPresent(context,
4293                                                     context->getState().getProgramExecutable()))
4294     {
4295         context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
4296         return false;
4297     }
4298 
4299     return true;
4300 }
4301 
ValidateVertexAttribI4i(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint x,GLint y,GLint z,GLint w)4302 bool ValidateVertexAttribI4i(const Context *context,
4303                              angle::EntryPoint entryPoint,
4304                              GLuint index,
4305                              GLint x,
4306                              GLint y,
4307                              GLint z,
4308                              GLint w)
4309 {
4310     if (context->getClientMajorVersion() < 3)
4311     {
4312         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4313         return false;
4314     }
4315 
4316     return ValidateVertexAttribIndex(context, entryPoint, index);
4317 }
4318 
ValidateVertexAttribI4ui(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)4319 bool ValidateVertexAttribI4ui(const Context *context,
4320                               angle::EntryPoint entryPoint,
4321                               GLuint index,
4322                               GLuint x,
4323                               GLuint y,
4324                               GLuint z,
4325                               GLuint w)
4326 {
4327     if (context->getClientMajorVersion() < 3)
4328     {
4329         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4330         return false;
4331     }
4332 
4333     return ValidateVertexAttribIndex(context, entryPoint, index);
4334 }
4335 
ValidateVertexAttribI4iv(const Context * context,angle::EntryPoint entryPoint,GLuint index,const GLint * v)4336 bool ValidateVertexAttribI4iv(const Context *context,
4337                               angle::EntryPoint entryPoint,
4338                               GLuint index,
4339                               const GLint *v)
4340 {
4341     if (context->getClientMajorVersion() < 3)
4342     {
4343         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4344         return false;
4345     }
4346 
4347     return ValidateVertexAttribIndex(context, entryPoint, index);
4348 }
4349 
ValidateVertexAttribI4uiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,const GLuint * v)4350 bool ValidateVertexAttribI4uiv(const Context *context,
4351                                angle::EntryPoint entryPoint,
4352                                GLuint index,
4353                                const GLuint *v)
4354 {
4355     if (context->getClientMajorVersion() < 3)
4356     {
4357         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4358         return false;
4359     }
4360 
4361     return ValidateVertexAttribIndex(context, entryPoint, index);
4362 }
4363 
ValidateGetFragDataLocation(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * name)4364 bool ValidateGetFragDataLocation(const Context *context,
4365                                  angle::EntryPoint entryPoint,
4366                                  ShaderProgramID program,
4367                                  const GLchar *name)
4368 {
4369     if (context->getClientMajorVersion() < 3)
4370     {
4371         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4372         return false;
4373     }
4374 
4375     Program *programObject = GetValidProgram(context, entryPoint, program);
4376     if (!programObject)
4377     {
4378         return false;
4379     }
4380 
4381     if (!programObject->isLinked())
4382     {
4383         context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
4384         return false;
4385     }
4386 
4387     return true;
4388 }
4389 
ValidateGetUniformIndices(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLchar * const * uniformNames,const GLuint * uniformIndices)4390 bool ValidateGetUniformIndices(const Context *context,
4391                                angle::EntryPoint entryPoint,
4392                                ShaderProgramID program,
4393                                GLsizei uniformCount,
4394                                const GLchar *const *uniformNames,
4395                                const GLuint *uniformIndices)
4396 {
4397     if (context->getClientMajorVersion() < 3)
4398     {
4399         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4400         return false;
4401     }
4402 
4403     if (uniformCount < 0)
4404     {
4405         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
4406         return false;
4407     }
4408 
4409     Program *programObject = GetValidProgram(context, entryPoint, program);
4410     if (!programObject)
4411     {
4412         return false;
4413     }
4414 
4415     return true;
4416 }
4417 
ValidateGetActiveUniformsiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,const GLint * params)4418 bool ValidateGetActiveUniformsiv(const Context *context,
4419                                  angle::EntryPoint entryPoint,
4420                                  ShaderProgramID program,
4421                                  GLsizei uniformCount,
4422                                  const GLuint *uniformIndices,
4423                                  GLenum pname,
4424                                  const GLint *params)
4425 {
4426     if (context->getClientMajorVersion() < 3)
4427     {
4428         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4429         return false;
4430     }
4431 
4432     if (uniformCount < 0)
4433     {
4434         context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
4435         return false;
4436     }
4437 
4438     Program *programObject = GetValidProgram(context, entryPoint, program);
4439     if (!programObject)
4440     {
4441         return false;
4442     }
4443 
4444     switch (pname)
4445     {
4446         case GL_UNIFORM_TYPE:
4447         case GL_UNIFORM_SIZE:
4448             break;
4449         case GL_UNIFORM_NAME_LENGTH:
4450             if (context->getExtensions().webglCompatibilityANGLE)
4451             {
4452                 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumNotSupported);
4453                 return false;
4454             }
4455             break;
4456         case GL_UNIFORM_BLOCK_INDEX:
4457         case GL_UNIFORM_OFFSET:
4458         case GL_UNIFORM_ARRAY_STRIDE:
4459         case GL_UNIFORM_MATRIX_STRIDE:
4460         case GL_UNIFORM_IS_ROW_MAJOR:
4461             break;
4462 
4463         default:
4464             context->validationError(entryPoint, GL_INVALID_ENUM, kEnumNotSupported);
4465             return false;
4466     }
4467 
4468     if (uniformCount > programObject->getActiveUniformCount())
4469     {
4470         context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4471         return false;
4472     }
4473 
4474     for (int uniformId = 0; uniformId < uniformCount; uniformId++)
4475     {
4476         const GLuint index = uniformIndices[uniformId];
4477 
4478         if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4479         {
4480             context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4481             return false;
4482         }
4483     }
4484 
4485     return true;
4486 }
4487 
ValidateGetUniformBlockIndex(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * uniformBlockName)4488 bool ValidateGetUniformBlockIndex(const Context *context,
4489                                   angle::EntryPoint entryPoint,
4490                                   ShaderProgramID program,
4491                                   const GLchar *uniformBlockName)
4492 {
4493     if (context->getClientMajorVersion() < 3)
4494     {
4495         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4496         return false;
4497     }
4498 
4499     Program *programObject = GetValidProgram(context, entryPoint, program);
4500     if (!programObject)
4501     {
4502         return false;
4503     }
4504 
4505     return true;
4506 }
4507 
ValidateGetActiveUniformBlockiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,const GLint * params)4508 bool ValidateGetActiveUniformBlockiv(const Context *context,
4509                                      angle::EntryPoint entryPoint,
4510                                      ShaderProgramID program,
4511                                      UniformBlockIndex uniformBlockIndex,
4512                                      GLenum pname,
4513                                      const GLint *params)
4514 {
4515     return ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex,
4516                                                pname, nullptr);
4517 }
4518 
ValidateGetActiveUniformBlockName(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLsizei bufSize,const GLsizei * length,const GLchar * uniformBlockName)4519 bool ValidateGetActiveUniformBlockName(const Context *context,
4520                                        angle::EntryPoint entryPoint,
4521                                        ShaderProgramID program,
4522                                        UniformBlockIndex uniformBlockIndex,
4523                                        GLsizei bufSize,
4524                                        const GLsizei *length,
4525                                        const GLchar *uniformBlockName)
4526 {
4527     if (context->getClientMajorVersion() < 3)
4528     {
4529         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4530         return false;
4531     }
4532 
4533     Program *programObject = GetValidProgram(context, entryPoint, program);
4534     if (!programObject)
4535     {
4536         return false;
4537     }
4538 
4539     if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
4540     {
4541         context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
4542         return false;
4543     }
4544 
4545     return true;
4546 }
4547 
ValidateUniformBlockBinding(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)4548 bool ValidateUniformBlockBinding(const Context *context,
4549                                  angle::EntryPoint entryPoint,
4550                                  ShaderProgramID program,
4551                                  UniformBlockIndex uniformBlockIndex,
4552                                  GLuint uniformBlockBinding)
4553 {
4554     if (context->getClientMajorVersion() < 3)
4555     {
4556         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4557         return false;
4558     }
4559 
4560     if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
4561     {
4562         context->validationError(entryPoint, GL_INVALID_VALUE,
4563                                  kIndexExceedsMaxUniformBufferBindings);
4564         return false;
4565     }
4566 
4567     Program *programObject = GetValidProgram(context, entryPoint, program);
4568     if (!programObject)
4569     {
4570         return false;
4571     }
4572 
4573     // if never linked, there won't be any uniform blocks
4574     if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
4575     {
4576         context->validationError(entryPoint, GL_INVALID_VALUE,
4577                                  kIndexExceedsMaxUniformBufferBindings);
4578         return false;
4579     }
4580 
4581     return true;
4582 }
4583 
ValidateDrawArraysInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4584 bool ValidateDrawArraysInstanced(const Context *context,
4585                                  angle::EntryPoint entryPoint,
4586                                  PrimitiveMode mode,
4587                                  GLint first,
4588                                  GLsizei count,
4589                                  GLsizei primcount)
4590 {
4591     if (context->getClientMajorVersion() < 3)
4592     {
4593         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4594         return false;
4595     }
4596 
4597     return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount);
4598 }
4599 
ValidateFenceSync(const Context * context,angle::EntryPoint entryPoint,GLenum condition,GLbitfield flags)4600 bool ValidateFenceSync(const Context *context,
4601                        angle::EntryPoint entryPoint,
4602                        GLenum condition,
4603                        GLbitfield flags)
4604 {
4605     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4606     {
4607         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4608         return false;
4609     }
4610 
4611     if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
4612     {
4613         context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition);
4614         return false;
4615     }
4616 
4617     if (flags != 0)
4618     {
4619         context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
4620         return false;
4621     }
4622 
4623     return true;
4624 }
4625 
ValidateIsSync(const Context * context,angle::EntryPoint entryPoint,GLsync sync)4626 bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
4627 {
4628     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4629     {
4630         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4631         return false;
4632     }
4633 
4634     return true;
4635 }
4636 
ValidateDeleteSync(const Context * context,angle::EntryPoint entryPoint,GLsync sync)4637 bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
4638 {
4639     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4640     {
4641         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4642         return false;
4643     }
4644 
4645     if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
4646     {
4647         context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
4648         return false;
4649     }
4650 
4651     return true;
4652 }
4653 
ValidateClientWaitSync(const Context * context,angle::EntryPoint entryPoint,GLsync sync,GLbitfield flags,GLuint64 timeout)4654 bool ValidateClientWaitSync(const Context *context,
4655                             angle::EntryPoint entryPoint,
4656                             GLsync sync,
4657                             GLbitfield flags,
4658                             GLuint64 timeout)
4659 {
4660     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4661     {
4662         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4663         return false;
4664     }
4665 
4666     if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
4667     {
4668         context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
4669         return false;
4670     }
4671 
4672     Sync *clientWaitSync = context->getSync(sync);
4673     if (!clientWaitSync)
4674     {
4675         context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
4676         return false;
4677     }
4678 
4679     return true;
4680 }
4681 
ValidateWaitSync(const Context * context,angle::EntryPoint entryPoint,GLsync sync,GLbitfield flags,GLuint64 timeout)4682 bool ValidateWaitSync(const Context *context,
4683                       angle::EntryPoint entryPoint,
4684                       GLsync sync,
4685                       GLbitfield flags,
4686                       GLuint64 timeout)
4687 {
4688     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4689     {
4690         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4691         return false;
4692     }
4693 
4694     if (flags != 0)
4695     {
4696         context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
4697         return false;
4698     }
4699 
4700     if (timeout != GL_TIMEOUT_IGNORED)
4701     {
4702         context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTimeout);
4703         return false;
4704     }
4705 
4706     Sync *waitSync = context->getSync(sync);
4707     if (!waitSync)
4708     {
4709         context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
4710         return false;
4711     }
4712 
4713     return true;
4714 }
4715 
ValidateGetInteger64v(const Context * context,angle::EntryPoint entryPoint,GLenum pname,const GLint64 * params)4716 bool ValidateGetInteger64v(const Context *context,
4717                            angle::EntryPoint entryPoint,
4718                            GLenum pname,
4719                            const GLint64 *params)
4720 {
4721     if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4722     {
4723         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4724         return false;
4725     }
4726 
4727     GLenum nativeType      = GL_NONE;
4728     unsigned int numParams = 0;
4729     if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
4730     {
4731         return false;
4732     }
4733 
4734     return true;
4735 }
4736 
ValidateIsSampler(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler)4737 bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler)
4738 {
4739     if (context->getClientMajorVersion() < 3)
4740     {
4741         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4742         return false;
4743     }
4744 
4745     return true;
4746 }
4747 
ValidateBindSampler(const Context * context,angle::EntryPoint entryPoint,GLuint unit,SamplerID sampler)4748 bool ValidateBindSampler(const Context *context,
4749                          angle::EntryPoint entryPoint,
4750                          GLuint unit,
4751                          SamplerID sampler)
4752 {
4753     if (context->getClientMajorVersion() < 3)
4754     {
4755         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4756         return false;
4757     }
4758 
4759     if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
4760     {
4761         context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
4762         return false;
4763     }
4764 
4765     if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
4766     {
4767         context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCombinedImageUnit);
4768         return false;
4769     }
4770 
4771     return true;
4772 }
4773 
ValidateVertexAttribDivisor(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLuint divisor)4774 bool ValidateVertexAttribDivisor(const Context *context,
4775                                  angle::EntryPoint entryPoint,
4776                                  GLuint index,
4777                                  GLuint divisor)
4778 {
4779     if (context->getClientMajorVersion() < 3)
4780     {
4781         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4782         return false;
4783     }
4784 
4785     return ValidateVertexAttribIndex(context, entryPoint, index);
4786 }
4787 
ValidateTexStorage2D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)4788 bool ValidateTexStorage2D(const Context *context,
4789                           angle::EntryPoint entryPoint,
4790                           TextureType target,
4791                           GLsizei levels,
4792                           GLenum internalformat,
4793                           GLsizei width,
4794                           GLsizei height)
4795 {
4796     if (context->getClientMajorVersion() < 3)
4797     {
4798         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4799         return false;
4800     }
4801 
4802     if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat,
4803                                            width, height, 1))
4804     {
4805         return false;
4806     }
4807 
4808     return true;
4809 }
4810 
ValidateTexStorage3D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)4811 bool ValidateTexStorage3D(const Context *context,
4812                           angle::EntryPoint entryPoint,
4813                           TextureType target,
4814                           GLsizei levels,
4815                           GLenum internalformat,
4816                           GLsizei width,
4817                           GLsizei height,
4818                           GLsizei depth)
4819 {
4820     if (context->getClientMajorVersion() < 3)
4821     {
4822         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4823         return false;
4824     }
4825 
4826     if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
4827                                            width, height, depth))
4828     {
4829         return false;
4830     }
4831 
4832     return true;
4833 }
4834 
ValidateGetBufferParameteri64v(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,const GLint64 * params)4835 bool ValidateGetBufferParameteri64v(const Context *context,
4836                                     angle::EntryPoint entryPoint,
4837                                     BufferBinding target,
4838                                     GLenum pname,
4839                                     const GLint64 *params)
4840 {
4841     return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
4842 }
4843 
ValidateGetSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)4844 bool ValidateGetSamplerParameterfv(const Context *context,
4845                                    angle::EntryPoint entryPoint,
4846                                    SamplerID sampler,
4847                                    GLenum pname,
4848                                    const GLfloat *params)
4849 {
4850     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4851 }
4852 
ValidateGetSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4853 bool ValidateGetSamplerParameteriv(const Context *context,
4854                                    angle::EntryPoint entryPoint,
4855                                    SamplerID sampler,
4856                                    GLenum pname,
4857                                    const GLint *params)
4858 {
4859     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4860 }
4861 
ValidateGetSamplerParameterIivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4862 bool ValidateGetSamplerParameterIivOES(const Context *context,
4863                                        angle::EntryPoint entryPoint,
4864                                        SamplerID sampler,
4865                                        GLenum pname,
4866                                        const GLint *params)
4867 {
4868     if (context->getClientMajorVersion() < 3)
4869     {
4870         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4871         return false;
4872     }
4873     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4874 }
4875 
ValidateGetSamplerParameterIuivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLuint * params)4876 bool ValidateGetSamplerParameterIuivOES(const Context *context,
4877                                         angle::EntryPoint entryPoint,
4878                                         SamplerID sampler,
4879                                         GLenum pname,
4880                                         const GLuint *params)
4881 {
4882     if (context->getClientMajorVersion() < 3)
4883     {
4884         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4885         return false;
4886     }
4887     return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4888 }
4889 
ValidateSamplerParameterf(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLfloat param)4890 bool ValidateSamplerParameterf(const Context *context,
4891                                angle::EntryPoint entryPoint,
4892                                SamplerID sampler,
4893                                GLenum pname,
4894                                GLfloat param)
4895 {
4896     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
4897 }
4898 
ValidateSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)4899 bool ValidateSamplerParameterfv(const Context *context,
4900                                 angle::EntryPoint entryPoint,
4901                                 SamplerID sampler,
4902                                 GLenum pname,
4903                                 const GLfloat *params)
4904 {
4905     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
4906 }
4907 
ValidateSamplerParameteri(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLint param)4908 bool ValidateSamplerParameteri(const Context *context,
4909                                angle::EntryPoint entryPoint,
4910                                SamplerID sampler,
4911                                GLenum pname,
4912                                GLint param)
4913 {
4914     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
4915 }
4916 
ValidateSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4917 bool ValidateSamplerParameteriv(const Context *context,
4918                                 angle::EntryPoint entryPoint,
4919                                 SamplerID sampler,
4920                                 GLenum pname,
4921                                 const GLint *params)
4922 {
4923     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
4924 }
4925 
ValidateSamplerParameterIivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4926 bool ValidateSamplerParameterIivOES(const Context *context,
4927                                     angle::EntryPoint entryPoint,
4928                                     SamplerID sampler,
4929                                     GLenum pname,
4930                                     const GLint *params)
4931 {
4932     if (context->getClientMajorVersion() < 3)
4933     {
4934         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4935         return false;
4936     }
4937     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
4938 }
4939 
ValidateSamplerParameterIuivOES(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLuint * params)4940 bool ValidateSamplerParameterIuivOES(const Context *context,
4941                                      angle::EntryPoint entryPoint,
4942                                      SamplerID sampler,
4943                                      GLenum pname,
4944                                      const GLuint *params)
4945 {
4946     if (context->getClientMajorVersion() < 3)
4947     {
4948         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4949         return false;
4950     }
4951     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
4952 }
4953 
ValidateGetVertexAttribIiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLint * params)4954 bool ValidateGetVertexAttribIiv(const Context *context,
4955                                 angle::EntryPoint entryPoint,
4956                                 GLuint index,
4957                                 GLenum pname,
4958                                 const GLint *params)
4959 {
4960     return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
4961 }
4962 
ValidateGetVertexAttribIuiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLuint * params)4963 bool ValidateGetVertexAttribIuiv(const Context *context,
4964                                  angle::EntryPoint entryPoint,
4965                                  GLuint index,
4966                                  GLenum pname,
4967                                  const GLuint *params)
4968 {
4969     return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
4970 }
4971 
ValidateGetInternalformativ(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLint * params)4972 bool ValidateGetInternalformativ(const Context *context,
4973                                  angle::EntryPoint entryPoint,
4974                                  GLenum target,
4975                                  GLenum internalformat,
4976                                  GLenum pname,
4977                                  GLsizei bufSize,
4978                                  const GLint *params)
4979 {
4980     return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
4981                                            bufSize, nullptr);
4982 }
4983 
ValidateBindFragDataLocationIndexedEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,GLuint index,const char * name)4984 bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
4985                                             angle::EntryPoint entryPoint,
4986                                             ShaderProgramID program,
4987                                             GLuint colorNumber,
4988                                             GLuint index,
4989                                             const char *name)
4990 {
4991     if (!context->getExtensions().blendFuncExtendedEXT)
4992     {
4993         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
4994         return false;
4995     }
4996     if (context->getClientMajorVersion() < 3)
4997     {
4998         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4999         return false;
5000     }
5001     if (index > 1)
5002     {
5003         // This error is not explicitly specified but the spec does say that "<index> may be zero or
5004         // one to specify that the color be used as either the first or second color input to the
5005         // blend equation, respectively"
5006         context->validationError(entryPoint, GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
5007         return false;
5008     }
5009     if (index == 1)
5010     {
5011         if (colorNumber >= context->getCaps().maxDualSourceDrawBuffers)
5012         {
5013             context->validationError(entryPoint, GL_INVALID_VALUE,
5014                                      kColorNumberGreaterThanMaxDualSourceDrawBuffers);
5015             return false;
5016         }
5017     }
5018     else
5019     {
5020         if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
5021         {
5022             context->validationError(entryPoint, GL_INVALID_VALUE,
5023                                      kColorNumberGreaterThanMaxDrawBuffers);
5024             return false;
5025         }
5026     }
5027     Program *programObject = GetValidProgram(context, entryPoint, program);
5028     if (!programObject)
5029     {
5030         return false;
5031     }
5032     return true;
5033 }
5034 
ValidateBindFragDataLocationEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,const char * name)5035 bool ValidateBindFragDataLocationEXT(const Context *context,
5036                                      angle::EntryPoint entryPoint,
5037                                      ShaderProgramID program,
5038                                      GLuint colorNumber,
5039                                      const char *name)
5040 {
5041     return ValidateBindFragDataLocationIndexedEXT(context, entryPoint, program, colorNumber, 0u,
5042                                                   name);
5043 }
5044 
ValidateGetFragDataIndexEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const char * name)5045 bool ValidateGetFragDataIndexEXT(const Context *context,
5046                                  angle::EntryPoint entryPoint,
5047                                  ShaderProgramID program,
5048                                  const char *name)
5049 {
5050     if (!context->getExtensions().blendFuncExtendedEXT)
5051     {
5052         context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
5053         return false;
5054     }
5055     if (context->getClientMajorVersion() < 3)
5056     {
5057         context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
5058         return false;
5059     }
5060     Program *programObject = GetValidProgram(context, entryPoint, program);
5061     if (!programObject)
5062     {
5063         return false;
5064     }
5065     if (!programObject->isLinked())
5066     {
5067         context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
5068         return false;
5069     }
5070     return true;
5071 }
5072 
ValidateTexStorage2DMultisampleANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)5073 bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
5074                                           angle::EntryPoint entryPoint,
5075                                           TextureType target,
5076                                           GLsizei samples,
5077                                           GLenum internalFormat,
5078                                           GLsizei width,
5079                                           GLsizei height,
5080                                           GLboolean fixedSampleLocations)
5081 {
5082     if (!context->getExtensions().textureMultisampleANGLE)
5083     {
5084         context->validationError(entryPoint, GL_INVALID_OPERATION,
5085                                  kMultisampleTextureExtensionOrES31Required);
5086         return false;
5087     }
5088 
5089     return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
5090                                                width, height);
5091 }
5092 
ValidateGetTexLevelParameterfvANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLfloat * params)5093 bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
5094                                          angle::EntryPoint entryPoint,
5095                                          TextureTarget target,
5096                                          GLint level,
5097                                          GLenum pname,
5098                                          const GLfloat *params)
5099 {
5100     if (!context->getExtensions().textureMultisampleANGLE &&
5101         !context->getExtensions().getTexLevelParameterANGLE)
5102     {
5103         context->validationError(
5104             entryPoint, GL_INVALID_OPERATION,
5105             kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5106         return false;
5107     }
5108 
5109     return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5110 }
5111 
ValidateGetTexLevelParameterivANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLint * params)5112 bool ValidateGetTexLevelParameterivANGLE(const Context *context,
5113                                          angle::EntryPoint entryPoint,
5114                                          TextureTarget target,
5115                                          GLint level,
5116                                          GLenum pname,
5117                                          const GLint *params)
5118 {
5119     if (!context->getExtensions().textureMultisampleANGLE &&
5120         !context->getExtensions().getTexLevelParameterANGLE)
5121     {
5122         context->validationError(
5123             entryPoint, GL_INVALID_OPERATION,
5124             kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5125         return false;
5126     }
5127 
5128     return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5129 }
5130 
ValidateGetMultisamplefvANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,const GLfloat * val)5131 bool ValidateGetMultisamplefvANGLE(const Context *context,
5132                                    angle::EntryPoint entryPoint,
5133                                    GLenum pname,
5134                                    GLuint index,
5135                                    const GLfloat *val)
5136 {
5137     if (!context->getExtensions().textureMultisampleANGLE)
5138     {
5139         context->validationError(entryPoint, GL_INVALID_OPERATION,
5140                                  kMultisampleTextureExtensionOrES31Required);
5141         return false;
5142     }
5143 
5144     return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
5145 }
5146 
ValidateSampleMaskiANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint maskNumber,GLbitfield mask)5147 bool ValidateSampleMaskiANGLE(const Context *context,
5148                               angle::EntryPoint entryPoint,
5149                               GLuint maskNumber,
5150                               GLbitfield mask)
5151 {
5152     if (!context->getExtensions().textureMultisampleANGLE)
5153     {
5154         context->validationError(entryPoint, GL_INVALID_OPERATION,
5155                                  kMultisampleTextureExtensionOrES31Required);
5156         return false;
5157     }
5158 
5159     return ValidateSampleMaskiBase(context, entryPoint, maskNumber, mask);
5160 }
5161 }  // namespace gl
5162