• 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 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
8 
9 #include "libANGLE/validationES.h"
10 
11 #include "libANGLE/Context.h"
12 #include "libANGLE/Display.h"
13 #include "libANGLE/ErrorStrings.h"
14 #include "libANGLE/Framebuffer.h"
15 #include "libANGLE/FramebufferAttachment.h"
16 #include "libANGLE/Image.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/Query.h"
19 #include "libANGLE/Texture.h"
20 #include "libANGLE/TransformFeedback.h"
21 #include "libANGLE/angletypes.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/queryconversions.h"
24 #include "libANGLE/queryutils.h"
25 #include "libANGLE/validationES2.h"
26 #include "libANGLE/validationES3.h"
27 
28 #include "common/mathutil.h"
29 #include "common/utilities.h"
30 
31 using namespace angle;
32 
33 namespace gl
34 {
35 using namespace err;
36 
37 namespace
38 {
CompressedTextureFormatRequiresExactSize(GLenum internalFormat)39 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
40 {
41     // List of compressed format that require that the texture size is smaller than or a multiple of
42     // the compressed block size.
43     switch (internalFormat)
44     {
45         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
46         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
47         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
48         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
49         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
50         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
51         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
52         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
53         case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
54         case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
55         case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
56         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
58         case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59         case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
60         case GL_COMPRESSED_RED_RGTC1_EXT:
61         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
62         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
63         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
64         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
65         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
66         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
67         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
68             return true;
69 
70         default:
71             return false;
72     }
73 }
CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)74 bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
75 {
76     // Compressed sub textures have additional formats that requires exact size.
77     // ES 3.1, Section 8.7, Page 171
78     return CompressedTextureFormatRequiresExactSize(internalFormat) ||
79            IsETC2EACFormat(internalFormat);
80 }
81 
DifferenceCanOverflow(GLint a,GLint b)82 bool DifferenceCanOverflow(GLint a, GLint b)
83 {
84     CheckedNumeric<GLint> checkedA(a);
85     checkedA -= b;
86     // Use negation to make sure that the difference can't overflow regardless of the order.
87     checkedA = -checkedA;
88     return !checkedA.IsValid();
89 }
90 
ValidReadPixelsTypeEnum(const Context * context,GLenum type)91 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
92 {
93     switch (type)
94     {
95         // Types referenced in Table 3.4 of the ES 2.0.25 spec
96         case GL_UNSIGNED_BYTE:
97         case GL_UNSIGNED_SHORT_4_4_4_4:
98         case GL_UNSIGNED_SHORT_5_5_5_1:
99         case GL_UNSIGNED_SHORT_5_6_5:
100             return context->getClientVersion() >= ES_2_0;
101 
102         // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
103         case GL_BYTE:
104         case GL_INT:
105         case GL_SHORT:
106         case GL_UNSIGNED_INT:
107         case GL_UNSIGNED_INT_10F_11F_11F_REV:
108         case GL_UNSIGNED_INT_24_8:
109         case GL_UNSIGNED_INT_2_10_10_10_REV:
110         case GL_UNSIGNED_INT_5_9_9_9_REV:
111         case GL_UNSIGNED_SHORT:
112         case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
113         case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
114             return context->getClientVersion() >= ES_3_0;
115 
116         case GL_FLOAT:
117             return context->getClientVersion() >= ES_3_0 ||
118                    context->getExtensions().textureFloatOES ||
119                    context->getExtensions().colorBufferHalfFloat;
120 
121         case GL_HALF_FLOAT:
122             return context->getClientVersion() >= ES_3_0 ||
123                    context->getExtensions().textureHalfFloat;
124 
125         case GL_HALF_FLOAT_OES:
126             return context->getExtensions().colorBufferHalfFloat;
127 
128         default:
129             return false;
130     }
131 }
132 
ValidReadPixelsFormatEnum(const Context * context,GLenum format)133 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
134 {
135     switch (format)
136     {
137         // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
138         case GL_RGBA:
139         case GL_RGB:
140         case GL_ALPHA:
141             return context->getClientVersion() >= ES_2_0;
142 
143         // Formats referenced in Table 3.2 of the ES 3.0.5 spec
144         case GL_RG:
145         case GL_RED:
146         case GL_RGBA_INTEGER:
147         case GL_RGB_INTEGER:
148         case GL_RG_INTEGER:
149         case GL_RED_INTEGER:
150             return context->getClientVersion() >= ES_3_0;
151 
152         case GL_SRGB_ALPHA_EXT:
153         case GL_SRGB_EXT:
154             return context->getExtensions().sRGB;
155 
156         case GL_BGRA_EXT:
157             return context->getExtensions().readFormatBGRA;
158 
159         default:
160             return false;
161     }
162 }
163 
ValidReadPixelsUnsignedNormalizedDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)164 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
165                                                 const gl::InternalFormat *info,
166                                                 GLenum type)
167 {
168     bool supportsReadDepthNV = (context->getExtensions().readDepthNV && (info->depthBits > 0) &&
169                                 (info->componentCount == 1));
170     bool isGLES31            = (context->getClientVersion() >= ES_3_1);
171     switch (type)
172     {
173         case GL_UNSIGNED_SHORT:
174             return supportsReadDepthNV ||
175                    (isGLES31 && (info->sizedInternalFormat == GL_DEPTH_COMPONENT16));
176         case GL_UNSIGNED_INT:
177             return supportsReadDepthNV ||
178                    (isGLES31 && ((info->sizedInternalFormat == GL_DEPTH_COMPONENT16) ||
179                                  (info->internalFormat == GL_DEPTH_COMPONENT24)));
180         case GL_UNSIGNED_INT_24_8:
181             return supportsReadDepthNV ||
182                    (isGLES31 && (info->sizedInternalFormat == GL_DEPTH24_STENCIL8));
183         default:
184             return false;
185     }
186 }
187 
ValidReadPixelsFloatDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)188 bool ValidReadPixelsFloatDepthType(const Context *context,
189                                    const gl::InternalFormat *info,
190                                    GLenum type)
191 {
192     return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
193            context->getExtensions().depthBufferFloat2NV && (info->componentCount == 1);
194 }
195 
ValidReadPixelsFormatType(const Context * context,const gl::InternalFormat * info,GLenum format,GLenum type)196 bool ValidReadPixelsFormatType(const Context *context,
197                                const gl::InternalFormat *info,
198                                GLenum format,
199                                GLenum type)
200 {
201     switch (info->componentType)
202     {
203         case GL_UNSIGNED_NORMALIZED:
204             // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
205             // ReadPixels with BGRA even if the extension is not present
206             switch (format)
207             {
208                 case GL_RGBA:
209                     return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) ||
210                            (context->getExtensions().textureNorm16 && (type == GL_UNSIGNED_SHORT) &&
211                             info->pixelBytes >= 2);
212                 case GL_BGRA_EXT:
213                     return context->getExtensions().readFormatBGRA && (type == GL_UNSIGNED_BYTE);
214                 case GL_STENCIL_INDEX_OES:
215                     return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
216                 case GL_DEPTH_COMPONENT:
217                     return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
218                 default:
219                     return false;
220             }
221         case GL_SIGNED_NORMALIZED:
222             return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) ||
223                    (context->getExtensions().textureNorm16 && format == GL_RGBA &&
224                     type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2);
225 
226         case GL_INT:
227             return (format == GL_RGBA_INTEGER && type == GL_INT);
228 
229         case GL_UNSIGNED_INT:
230             return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
231 
232         case GL_FLOAT:
233             switch (format)
234             {
235                 case GL_RGBA:
236                     return (type == GL_FLOAT);
237                 case GL_DEPTH_COMPONENT:
238                     return ValidReadPixelsFloatDepthType(context, info, type);
239                 default:
240                     return false;
241             }
242         default:
243             UNREACHABLE();
244             return false;
245     }
246 }
247 
248 template <typename ParamType>
ValidateTextureWrapModeValue(const Context * context,const ParamType * params,bool restrictedWrapModes)249 bool ValidateTextureWrapModeValue(const Context *context,
250                                   const ParamType *params,
251                                   bool restrictedWrapModes)
252 {
253     switch (ConvertToGLenum(params[0]))
254     {
255         case GL_CLAMP_TO_EDGE:
256             break;
257 
258         case GL_CLAMP_TO_BORDER:
259             if (!context->getExtensions().textureBorderClampOES)
260             {
261                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
262                 return false;
263             }
264             break;
265 
266         case GL_REPEAT:
267         case GL_MIRRORED_REPEAT:
268             if (restrictedWrapModes)
269             {
270                 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
271                 context->validationError(GL_INVALID_ENUM, kInvalidWrapModeTexture);
272                 return false;
273             }
274             break;
275 
276         default:
277             context->validationError(GL_INVALID_ENUM, kInvalidTextureWrap);
278             return false;
279     }
280 
281     return true;
282 }
283 
284 template <typename ParamType>
ValidateTextureMinFilterValue(const Context * context,const ParamType * params,bool restrictedMinFilter)285 bool ValidateTextureMinFilterValue(const Context *context,
286                                    const ParamType *params,
287                                    bool restrictedMinFilter)
288 {
289     switch (ConvertToGLenum(params[0]))
290     {
291         case GL_NEAREST:
292         case GL_LINEAR:
293             break;
294 
295         case GL_NEAREST_MIPMAP_NEAREST:
296         case GL_LINEAR_MIPMAP_NEAREST:
297         case GL_NEAREST_MIPMAP_LINEAR:
298         case GL_LINEAR_MIPMAP_LINEAR:
299             if (restrictedMinFilter)
300             {
301                 // OES_EGL_image_external specifies this error.
302                 context->validationError(GL_INVALID_ENUM, kInvalidFilterTexture);
303                 return false;
304             }
305             break;
306 
307         default:
308             context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
309             return false;
310     }
311 
312     return true;
313 }
314 
315 template <typename ParamType>
ValidateTextureMagFilterValue(const Context * context,const ParamType * params)316 bool ValidateTextureMagFilterValue(const Context *context, const ParamType *params)
317 {
318     switch (ConvertToGLenum(params[0]))
319     {
320         case GL_NEAREST:
321         case GL_LINEAR:
322             break;
323 
324         default:
325             context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
326             return false;
327     }
328 
329     return true;
330 }
331 
332 template <typename ParamType>
ValidateTextureCompareModeValue(const Context * context,const ParamType * params)333 bool ValidateTextureCompareModeValue(const Context *context, const ParamType *params)
334 {
335     // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
336     switch (ConvertToGLenum(params[0]))
337     {
338         case GL_NONE:
339         case GL_COMPARE_REF_TO_TEXTURE:
340             break;
341 
342         default:
343             context->validationError(GL_INVALID_ENUM, kUnknownParameter);
344             return false;
345     }
346 
347     return true;
348 }
349 
350 template <typename ParamType>
ValidateTextureCompareFuncValue(const Context * context,const ParamType * params)351 bool ValidateTextureCompareFuncValue(const Context *context, const ParamType *params)
352 {
353     // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
354     switch (ConvertToGLenum(params[0]))
355     {
356         case GL_LEQUAL:
357         case GL_GEQUAL:
358         case GL_LESS:
359         case GL_GREATER:
360         case GL_EQUAL:
361         case GL_NOTEQUAL:
362         case GL_ALWAYS:
363         case GL_NEVER:
364             break;
365 
366         default:
367             context->validationError(GL_INVALID_ENUM, kUnknownParameter);
368             return false;
369     }
370 
371     return true;
372 }
373 
374 template <typename ParamType>
ValidateTextureSRGBDecodeValue(const Context * context,const ParamType * params)375 bool ValidateTextureSRGBDecodeValue(const Context *context, const ParamType *params)
376 {
377     if (!context->getExtensions().textureSRGBDecode)
378     {
379         context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
380         return false;
381     }
382 
383     switch (ConvertToGLenum(params[0]))
384     {
385         case GL_DECODE_EXT:
386         case GL_SKIP_DECODE_EXT:
387             break;
388 
389         default:
390             context->validationError(GL_INVALID_ENUM, kUnknownParameter);
391             return false;
392     }
393 
394     return true;
395 }
396 
ValidateTextureMaxAnisotropyExtensionEnabled(const Context * context)397 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context)
398 {
399     if (!context->getExtensions().textureFilterAnisotropic)
400     {
401         context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
402         return false;
403     }
404 
405     return true;
406 }
407 
ValidateTextureMaxAnisotropyValue(const Context * context,GLfloat paramValue)408 bool ValidateTextureMaxAnisotropyValue(const Context *context, GLfloat paramValue)
409 {
410     if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
411     {
412         return false;
413     }
414 
415     GLfloat largest = context->getExtensions().maxTextureAnisotropy;
416 
417     if (paramValue < 1 || paramValue > largest)
418     {
419         context->validationError(GL_INVALID_VALUE, kOutsideOfBounds);
420         return false;
421     }
422 
423     return true;
424 }
425 
ValidateFragmentShaderColorBufferMaskMatch(const Context * context)426 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
427 {
428     const Program *program         = context->getActiveLinkedProgram();
429     const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
430 
431     auto drawBufferMask     = framebuffer->getDrawBufferMask().to_ulong();
432     auto fragmentOutputMask = program->getActiveOutputVariables().to_ulong();
433 
434     return drawBufferMask == (drawBufferMask & fragmentOutputMask);
435 }
436 
ValidateFragmentShaderColorBufferTypeMatch(const Context * context)437 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
438 {
439     const Program *program         = context->getActiveLinkedProgram();
440     const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
441 
442     return ValidateComponentTypeMasks(program->getDrawBufferTypeMask().to_ulong(),
443                                       framebuffer->getDrawBufferTypeMask().to_ulong(),
444                                       program->getActiveOutputVariables().to_ulong(),
445                                       framebuffer->getDrawBufferMask().to_ulong());
446 }
447 
ValidateVertexShaderAttributeTypeMatch(const Context * context)448 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
449 {
450     const auto &glState    = context->getState();
451     const Program *program = context->getActiveLinkedProgram();
452     const VertexArray *vao = context->getState().getVertexArray();
453 
454     unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
455     unsigned long vaoAttribTypeBits          = vao->getAttributesTypeMask().to_ulong();
456     unsigned long vaoAttribEnabledMask       = vao->getAttributesMask().to_ulong();
457 
458     vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
459     vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
460     vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
461 
462     return ValidateComponentTypeMasks(
463         program->getExecutable().getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
464         program->getExecutable().getAttributesMask().to_ulong(), 0xFFFF);
465 }
466 
IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,PrimitiveMode geometryShaderInputPrimitiveType)467 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
468                                             PrimitiveMode geometryShaderInputPrimitiveType)
469 {
470     // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
471     switch (drawMode)
472     {
473         case PrimitiveMode::Points:
474             return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
475         case PrimitiveMode::Lines:
476         case PrimitiveMode::LineStrip:
477         case PrimitiveMode::LineLoop:
478             return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
479         case PrimitiveMode::LinesAdjacency:
480         case PrimitiveMode::LineStripAdjacency:
481             return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
482         case PrimitiveMode::Triangles:
483         case PrimitiveMode::TriangleFan:
484         case PrimitiveMode::TriangleStrip:
485             return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
486         case PrimitiveMode::TrianglesAdjacency:
487         case PrimitiveMode::TriangleStripAdjacency:
488             return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
489         default:
490             UNREACHABLE();
491             return false;
492     }
493 }
494 
495 // GLES1 texture parameters are a small subset of the others
IsValidGLES1TextureParameter(GLenum pname)496 bool IsValidGLES1TextureParameter(GLenum pname)
497 {
498     switch (pname)
499     {
500         case GL_TEXTURE_MAG_FILTER:
501         case GL_TEXTURE_MIN_FILTER:
502         case GL_TEXTURE_WRAP_S:
503         case GL_TEXTURE_WRAP_T:
504         case GL_TEXTURE_WRAP_R:
505         case GL_GENERATE_MIPMAP:
506         case GL_TEXTURE_CROP_RECT_OES:
507             return true;
508         default:
509             return false;
510     }
511 }
512 
GetSamplerParameterCount(GLenum pname)513 unsigned int GetSamplerParameterCount(GLenum pname)
514 {
515     return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
516 }
517 
518 }  // anonymous namespace
519 
SetRobustLengthParam(const GLsizei * length,GLsizei value)520 void SetRobustLengthParam(const GLsizei *length, GLsizei value)
521 {
522     if (length)
523     {
524         // Currently we modify robust length parameters in the validation layer. We should be only
525         // doing this in the Context instead.
526         // TODO(http://anglebug.com/4406): Remove when possible.
527         *const_cast<GLsizei *>(length) = value;
528     }
529 }
530 
ValidTextureTarget(const Context * context,TextureType type)531 bool ValidTextureTarget(const Context *context, TextureType type)
532 {
533     switch (type)
534     {
535         case TextureType::_2D:
536         case TextureType::CubeMap:
537             return true;
538 
539         case TextureType::Rectangle:
540             return context->getExtensions().textureRectangle;
541 
542         case TextureType::_3D:
543             return ((context->getClientMajorVersion() >= 3) ||
544                     context->getExtensions().texture3DOES);
545 
546         case TextureType::_2DArray:
547             return (context->getClientMajorVersion() >= 3);
548 
549         case TextureType::_2DMultisample:
550             return (context->getClientVersion() >= Version(3, 1) ||
551                     context->getExtensions().textureMultisample);
552         case TextureType::_2DMultisampleArray:
553             return context->getExtensions().textureStorageMultisample2DArrayOES;
554 
555         case TextureType::VideoImage:
556             return context->getExtensions().webglVideoTexture;
557 
558         default:
559             return false;
560     }
561 }
562 
ValidTexture2DTarget(const Context * context,TextureType type)563 bool ValidTexture2DTarget(const Context *context, TextureType type)
564 {
565     switch (type)
566     {
567         case TextureType::_2D:
568         case TextureType::CubeMap:
569             return true;
570 
571         case TextureType::Rectangle:
572             return context->getExtensions().textureRectangle;
573 
574         default:
575             return false;
576     }
577 }
578 
ValidTexture3DTarget(const Context * context,TextureType target)579 bool ValidTexture3DTarget(const Context *context, TextureType target)
580 {
581     switch (target)
582     {
583         case TextureType::_3D:
584         case TextureType::_2DArray:
585             return (context->getClientMajorVersion() >= 3);
586 
587         default:
588             return false;
589     }
590 }
591 
592 // Most texture GL calls are not compatible with external textures, so we have a separate validation
593 // function for use in the GL calls that do
ValidTextureExternalTarget(const Context * context,TextureType target)594 bool ValidTextureExternalTarget(const Context *context, TextureType target)
595 {
596     return (target == TextureType::External) &&
597            (context->getExtensions().eglImageExternalOES ||
598             context->getExtensions().eglStreamConsumerExternalNV);
599 }
600 
ValidTextureExternalTarget(const Context * context,TextureTarget target)601 bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
602 {
603     return (target == TextureTarget::External) &&
604            ValidTextureExternalTarget(context, TextureType::External);
605 }
606 
607 // This function differs from ValidTextureTarget in that the target must be
608 // usable as the destination of a 2D operation-- so a cube face is valid, but
609 // GL_TEXTURE_CUBE_MAP is not.
610 // Note: duplicate of IsInternalTextureTarget
ValidTexture2DDestinationTarget(const Context * context,TextureTarget target)611 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
612 {
613     switch (target)
614     {
615         case TextureTarget::_2D:
616         case TextureTarget::CubeMapNegativeX:
617         case TextureTarget::CubeMapNegativeY:
618         case TextureTarget::CubeMapNegativeZ:
619         case TextureTarget::CubeMapPositiveX:
620         case TextureTarget::CubeMapPositiveY:
621         case TextureTarget::CubeMapPositiveZ:
622             return true;
623         case TextureTarget::Rectangle:
624             return context->getExtensions().textureRectangle;
625         case TextureTarget::VideoImage:
626             return context->getExtensions().webglVideoTexture;
627         default:
628             return false;
629     }
630 }
631 
ValidateTransformFeedbackPrimitiveMode(const Context * context,PrimitiveMode transformFeedbackPrimitiveMode,PrimitiveMode renderPrimitiveMode)632 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
633                                             PrimitiveMode transformFeedbackPrimitiveMode,
634                                             PrimitiveMode renderPrimitiveMode)
635 {
636     ASSERT(context);
637 
638     if (!context->getExtensions().geometryShader)
639     {
640         // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
641         // that does not match the current transform feedback object's draw mode (if transform
642         // feedback is active), (3.0.2, section 2.14, pg 86)
643         return transformFeedbackPrimitiveMode == renderPrimitiveMode;
644     }
645 
646     // [GL_EXT_geometry_shader] Table 12.1gs
647     switch (renderPrimitiveMode)
648     {
649         case PrimitiveMode::Points:
650             return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
651         case PrimitiveMode::Lines:
652         case PrimitiveMode::LineStrip:
653         case PrimitiveMode::LineLoop:
654             return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
655         case PrimitiveMode::Triangles:
656         case PrimitiveMode::TriangleFan:
657         case PrimitiveMode::TriangleStrip:
658             return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
659         default:
660             UNREACHABLE();
661             return false;
662     }
663 }
664 
ValidateDrawElementsInstancedBase(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const GLvoid * indices,GLsizei primcount)665 bool ValidateDrawElementsInstancedBase(const Context *context,
666                                        PrimitiveMode mode,
667                                        GLsizei count,
668                                        DrawElementsType type,
669                                        const GLvoid *indices,
670                                        GLsizei primcount)
671 {
672     if (primcount <= 0)
673     {
674         if (primcount < 0)
675         {
676             context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
677             return false;
678         }
679 
680         // Early exit.
681         return ValidateDrawElementsCommon(context, mode, count, type, indices, primcount);
682     }
683 
684     if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
685     {
686         return false;
687     }
688 
689     if (count == 0)
690     {
691         // Early exit.
692         return true;
693     }
694 
695     return ValidateDrawInstancedAttribs(context, primcount);
696 }
697 
ValidateDrawArraysInstancedBase(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)698 bool ValidateDrawArraysInstancedBase(const Context *context,
699                                      PrimitiveMode mode,
700                                      GLint first,
701                                      GLsizei count,
702                                      GLsizei primcount)
703 {
704     if (primcount <= 0)
705     {
706         if (primcount < 0)
707         {
708             context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
709             return false;
710         }
711 
712         // Early exit.
713         return ValidateDrawArraysCommon(context, mode, first, count, primcount);
714     }
715 
716     if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
717     {
718         return false;
719     }
720 
721     if (count == 0)
722     {
723         // Early exit.
724         return true;
725     }
726 
727     return ValidateDrawInstancedAttribs(context, primcount);
728 }
729 
ValidateDrawInstancedANGLE(const Context * context)730 bool ValidateDrawInstancedANGLE(const Context *context)
731 {
732     // Verify there is at least one active attribute with a divisor of zero
733     const State &state                  = context->getState();
734     const ProgramExecutable *executable = state.getProgramExecutable();
735 
736     const auto &attribs  = state.getVertexArray()->getVertexAttributes();
737     const auto &bindings = state.getVertexArray()->getVertexBindings();
738     for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
739     {
740         const VertexAttribute &attrib = attribs[attributeIndex];
741         const VertexBinding &binding  = bindings[attrib.bindingIndex];
742         if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
743         {
744             return true;
745         }
746     }
747 
748     context->validationError(GL_INVALID_OPERATION, kNoZeroDivisor);
749     return false;
750 }
751 
ValidTexture3DDestinationTarget(const Context * context,TextureTarget target)752 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
753 {
754     switch (target)
755     {
756         case TextureTarget::_3D:
757         case TextureTarget::_2DArray:
758             return true;
759         default:
760             return false;
761     }
762 }
763 
ValidTexLevelDestinationTarget(const Context * context,TextureType type)764 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
765 {
766     switch (type)
767     {
768         case TextureType::_2D:
769         case TextureType::_2DArray:
770         case TextureType::_2DMultisample:
771         case TextureType::CubeMap:
772         case TextureType::_3D:
773             return true;
774         case TextureType::Rectangle:
775             return context->getExtensions().textureRectangle;
776         case TextureType::_2DMultisampleArray:
777             return context->getExtensions().textureStorageMultisample2DArrayOES;
778         default:
779             return false;
780     }
781 }
782 
ValidFramebufferTarget(const Context * context,GLenum target)783 bool ValidFramebufferTarget(const Context *context, GLenum target)
784 {
785     static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
786                       GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
787                   "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
788 
789     switch (target)
790     {
791         case GL_FRAMEBUFFER:
792             return true;
793 
794         case GL_READ_FRAMEBUFFER:
795         case GL_DRAW_FRAMEBUFFER:
796             return (context->getExtensions().framebufferBlit ||
797                     context->getClientMajorVersion() >= 3);
798 
799         default:
800             return false;
801     }
802 }
803 
ValidMipLevel(const Context * context,TextureType type,GLint level)804 bool ValidMipLevel(const Context *context, TextureType type, GLint level)
805 {
806     const auto &caps = context->getCaps();
807     int maxDimension = 0;
808     switch (type)
809     {
810         case TextureType::_2D:
811         case TextureType::_2DArray:
812         case TextureType::_2DMultisample:
813         case TextureType::_2DMultisampleArray:
814             // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
815             // level-of-detail" for multisample textures should be. Could maybe make it zero.
816             maxDimension = caps.max2DTextureSize;
817             break;
818 
819         case TextureType::CubeMap:
820             maxDimension = caps.maxCubeMapTextureSize;
821             break;
822 
823         case TextureType::External:
824         case TextureType::Rectangle:
825         case TextureType::VideoImage:
826             return level == 0;
827 
828         case TextureType::_3D:
829             maxDimension = caps.max3DTextureSize;
830             break;
831 
832         default:
833             UNREACHABLE();
834     }
835 
836     return level <= log2(maxDimension) && level >= 0;
837 }
838 
ValidImageSizeParameters(const Context * context,TextureType target,GLint level,GLsizei width,GLsizei height,GLsizei depth,bool isSubImage)839 bool ValidImageSizeParameters(const Context *context,
840                               TextureType target,
841                               GLint level,
842                               GLsizei width,
843                               GLsizei height,
844                               GLsizei depth,
845                               bool isSubImage)
846 {
847     if (width < 0 || height < 0 || depth < 0)
848     {
849         context->validationError(GL_INVALID_VALUE, kNegativeSize);
850         return false;
851     }
852     // TexSubImage parameters can be NPOT without textureNPOT extension,
853     // as long as the destination texture is POT.
854     bool hasNPOTSupport =
855         context->getExtensions().textureNPOTOES || context->getClientVersion() >= Version(3, 0);
856     if (!isSubImage && !hasNPOTSupport &&
857         (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
858     {
859         context->validationError(GL_INVALID_VALUE, kTextureNotPow2);
860         return false;
861     }
862 
863     if (!ValidMipLevel(context, target, level))
864     {
865         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
866         return false;
867     }
868 
869     return true;
870 }
871 
ValidCompressedDimension(GLsizei size,GLuint blockSize,bool smallerThanBlockSizeAllowed)872 bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
873 {
874     return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
875            (size % blockSize == 0);
876 }
877 
ValidCompressedImageSize(const Context * context,GLenum internalFormat,GLint level,GLsizei width,GLsizei height,GLsizei depth)878 bool ValidCompressedImageSize(const Context *context,
879                               GLenum internalFormat,
880                               GLint level,
881                               GLsizei width,
882                               GLsizei height,
883                               GLsizei depth)
884 {
885     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
886     if (!formatInfo.compressed)
887     {
888         return false;
889     }
890 
891     if (width < 0 || height < 0)
892     {
893         return false;
894     }
895 
896     if (CompressedTextureFormatRequiresExactSize(internalFormat))
897     {
898         // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
899         // block size for level 0 but WebGL disallows this.
900         bool smallerThanBlockSizeAllowed =
901             level > 0 || !context->getExtensions().webglCompatibility;
902 
903         if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
904                                       smallerThanBlockSizeAllowed) ||
905             !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
906                                       smallerThanBlockSizeAllowed) ||
907             !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth,
908                                       smallerThanBlockSizeAllowed))
909         {
910             return false;
911         }
912     }
913 
914     return true;
915 }
916 
ValidCompressedSubImageSize(const Context * context,GLenum internalFormat,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,size_t textureWidth,size_t textureHeight,size_t textureDepth)917 bool ValidCompressedSubImageSize(const Context *context,
918                                  GLenum internalFormat,
919                                  GLint xoffset,
920                                  GLint yoffset,
921                                  GLint zoffset,
922                                  GLsizei width,
923                                  GLsizei height,
924                                  GLsizei depth,
925                                  size_t textureWidth,
926                                  size_t textureHeight,
927                                  size_t textureDepth)
928 {
929     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
930     if (!formatInfo.compressed)
931     {
932         return false;
933     }
934 
935     if (xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0 || depth < 0)
936     {
937         return false;
938     }
939 
940     bool fillsEntireMip =
941         xoffset == 0 && yoffset == 0 && static_cast<size_t>(width) == textureWidth &&
942         static_cast<size_t>(height) == textureHeight && static_cast<size_t>(depth) == textureDepth;
943 
944     if (CompressedFormatRequiresWholeImage(internalFormat))
945     {
946         return fillsEntireMip;
947     }
948 
949     if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
950     {
951         if (xoffset % formatInfo.compressedBlockWidth != 0 ||
952             yoffset % formatInfo.compressedBlockHeight != 0 ||
953             zoffset % formatInfo.compressedBlockDepth != 0)
954         {
955             return false;
956         }
957 
958         // Allowed to either have data that is a multiple of block size or is smaller than the block
959         // size but fills the entire mip
960         bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
961                                        (height % formatInfo.compressedBlockHeight) == 0 &&
962                                        (depth % formatInfo.compressedBlockDepth) == 0;
963         if (!sizeMultipleOfBlockSize && !fillsEntireMip)
964         {
965             return false;
966         }
967     }
968 
969     return true;
970 }
971 
ValidImageDataSize(const Context * context,TextureType texType,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels,GLsizei imageSize)972 bool ValidImageDataSize(const Context *context,
973                         TextureType texType,
974                         GLsizei width,
975                         GLsizei height,
976                         GLsizei depth,
977                         GLenum format,
978                         GLenum type,
979                         const void *pixels,
980                         GLsizei imageSize)
981 {
982     Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
983     if (pixelUnpackBuffer == nullptr && imageSize < 0)
984     {
985         // Checks are not required
986         return true;
987     }
988 
989     // ...the data would be unpacked from the buffer object such that the memory reads required
990     // would exceed the data store size.
991     const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
992     ASSERT(formatInfo.internalFormat != GL_NONE);
993     const Extents size(width, height, depth);
994     const auto &unpack = context->getState().getUnpackState();
995 
996     bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
997     GLuint endByte  = 0;
998     if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
999     {
1000         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
1001         return false;
1002     }
1003 
1004     if (pixelUnpackBuffer)
1005     {
1006         CheckedNumeric<size_t> checkedEndByte(endByte);
1007         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1008         checkedEndByte += checkedOffset;
1009 
1010         if (!checkedEndByte.IsValid() ||
1011             (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1012         {
1013             // Overflow past the end of the buffer
1014             context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
1015             return false;
1016         }
1017         if (context->getExtensions().webglCompatibility &&
1018             pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
1019         {
1020             context->validationError(GL_INVALID_OPERATION,
1021                                      kPixelUnpackBufferBoundForTransformFeedback);
1022             return false;
1023         }
1024     }
1025     else
1026     {
1027         ASSERT(imageSize >= 0);
1028         if (pixels == nullptr && imageSize != 0)
1029         {
1030             context->validationError(GL_INVALID_OPERATION, kImageSizeMustBeZero);
1031             return false;
1032         }
1033 
1034         if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
1035         {
1036             context->validationError(GL_INVALID_OPERATION, kImageSizeTooSmall);
1037             return false;
1038         }
1039     }
1040 
1041     return true;
1042 }
1043 
ValidQueryType(const Context * context,QueryType queryType)1044 bool ValidQueryType(const Context *context, QueryType queryType)
1045 {
1046     switch (queryType)
1047     {
1048         case QueryType::AnySamples:
1049         case QueryType::AnySamplesConservative:
1050             return context->getClientMajorVersion() >= 3 ||
1051                    context->getExtensions().occlusionQueryBoolean;
1052         case QueryType::TransformFeedbackPrimitivesWritten:
1053             return (context->getClientMajorVersion() >= 3);
1054         case QueryType::TimeElapsed:
1055             return context->getExtensions().disjointTimerQuery;
1056         case QueryType::CommandsCompleted:
1057             return context->getExtensions().syncQuery;
1058         case QueryType::PrimitivesGenerated:
1059             return context->getExtensions().geometryShader;
1060         default:
1061             return false;
1062     }
1063 }
1064 
ValidateWebGLVertexAttribPointer(const Context * context,VertexAttribType type,GLboolean normalized,GLsizei stride,const void * ptr,bool pureInteger)1065 bool ValidateWebGLVertexAttribPointer(const Context *context,
1066                                       VertexAttribType type,
1067                                       GLboolean normalized,
1068                                       GLsizei stride,
1069                                       const void *ptr,
1070                                       bool pureInteger)
1071 {
1072     ASSERT(context->getExtensions().webglCompatibility);
1073     // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1074     // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1075     // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1076     // parameter exceeds 255.
1077     constexpr GLsizei kMaxWebGLStride = 255;
1078     if (stride > kMaxWebGLStride)
1079     {
1080         context->validationError(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
1081         return false;
1082     }
1083 
1084     // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1085     // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1086     // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1087     // or an INVALID_OPERATION error is generated.
1088     angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1089     size_t typeSize              = GetVertexFormatSize(internalType);
1090 
1091     ASSERT(isPow2(typeSize) && typeSize > 0);
1092     size_t sizeMask = (typeSize - 1);
1093     if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1094     {
1095         context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
1096         return false;
1097     }
1098 
1099     if ((stride & sizeMask) != 0)
1100     {
1101         context->validationError(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
1102         return false;
1103     }
1104 
1105     return true;
1106 }
1107 
GetValidProgramNoResolve(const Context * context,ShaderProgramID id)1108 Program *GetValidProgramNoResolve(const Context *context, ShaderProgramID id)
1109 {
1110     // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1111     // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1112     // or program object and INVALID_OPERATION if the provided name identifies an object
1113     // that is not the expected type."
1114 
1115     Program *validProgram = context->getProgramNoResolveLink(id);
1116 
1117     if (!validProgram)
1118     {
1119         if (context->getShader(id))
1120         {
1121             context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
1122         }
1123         else
1124         {
1125             context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
1126         }
1127     }
1128 
1129     return validProgram;
1130 }
1131 
GetValidProgram(const Context * context,ShaderProgramID id)1132 Program *GetValidProgram(const Context *context, ShaderProgramID id)
1133 {
1134     Program *program = GetValidProgramNoResolve(context, id);
1135     if (program)
1136     {
1137         program->resolveLink(context);
1138     }
1139     return program;
1140 }
1141 
GetValidShader(const Context * context,ShaderProgramID id)1142 Shader *GetValidShader(const Context *context, ShaderProgramID id)
1143 {
1144     // See ValidProgram for spec details.
1145 
1146     Shader *validShader = context->getShader(id);
1147 
1148     if (!validShader)
1149     {
1150         if (context->getProgramNoResolveLink(id))
1151         {
1152             context->validationError(GL_INVALID_OPERATION, kExpectedShaderName);
1153         }
1154         else
1155         {
1156             context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
1157         }
1158     }
1159 
1160     return validShader;
1161 }
1162 
ValidateAttachmentTarget(const Context * context,GLenum attachment)1163 bool ValidateAttachmentTarget(const Context *context, GLenum attachment)
1164 {
1165     if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1166     {
1167         if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1168         {
1169             context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1170             return false;
1171         }
1172 
1173         // Color attachment 0 is validated below because it is always valid
1174         const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1175         if (colorAttachment >= context->getCaps().maxColorAttachments)
1176         {
1177             context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
1178             return false;
1179         }
1180     }
1181     else
1182     {
1183         switch (attachment)
1184         {
1185             case GL_COLOR_ATTACHMENT0:
1186             case GL_DEPTH_ATTACHMENT:
1187             case GL_STENCIL_ATTACHMENT:
1188                 break;
1189 
1190             case GL_DEPTH_STENCIL_ATTACHMENT:
1191                 if (!context->getExtensions().webglCompatibility &&
1192                     context->getClientMajorVersion() < 3)
1193                 {
1194                     context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1195                     return false;
1196                 }
1197                 break;
1198 
1199             default:
1200                 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1201                 return false;
1202         }
1203     }
1204 
1205     return true;
1206 }
1207 
ValidateRenderbufferStorageParametersBase(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1208 bool ValidateRenderbufferStorageParametersBase(const Context *context,
1209                                                GLenum target,
1210                                                GLsizei samples,
1211                                                GLenum internalformat,
1212                                                GLsizei width,
1213                                                GLsizei height)
1214 {
1215     switch (target)
1216     {
1217         case GL_RENDERBUFFER:
1218             break;
1219         default:
1220             context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1221             return false;
1222     }
1223 
1224     if (width < 0 || height < 0 || samples < 0)
1225     {
1226         context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
1227         return false;
1228     }
1229 
1230     // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1231     GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1232 
1233     const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
1234     if (!formatCaps.renderbuffer)
1235     {
1236         context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1237         return false;
1238     }
1239 
1240     // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1241     // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
1242     // only sized internal formats.
1243     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
1244     if (formatInfo.internalFormat == GL_NONE)
1245     {
1246         context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1247         return false;
1248     }
1249 
1250     if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
1251     {
1252         context->validationError(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
1253         return false;
1254     }
1255 
1256     RenderbufferID id = context->getState().getRenderbufferId();
1257     if (id.value == 0)
1258     {
1259         context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1260         return false;
1261     }
1262 
1263     return true;
1264 }
1265 
ValidateFramebufferRenderbufferParameters(const Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)1266 bool ValidateFramebufferRenderbufferParameters(const Context *context,
1267                                                GLenum target,
1268                                                GLenum attachment,
1269                                                GLenum renderbuffertarget,
1270                                                RenderbufferID renderbuffer)
1271 {
1272     if (!ValidFramebufferTarget(context, target))
1273     {
1274         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1275         return false;
1276     }
1277 
1278     Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1279 
1280     ASSERT(framebuffer);
1281     if (framebuffer->isDefault())
1282     {
1283         context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
1284         return false;
1285     }
1286 
1287     if (!ValidateAttachmentTarget(context, attachment))
1288     {
1289         return false;
1290     }
1291 
1292     // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1293     // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1294     // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1295     // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1296     if (renderbuffer.value != 0)
1297     {
1298         if (!context->getRenderbuffer(renderbuffer))
1299         {
1300             context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1301             return false;
1302         }
1303     }
1304 
1305     return true;
1306 }
1307 
ValidateBlitFramebufferParameters(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1308 bool ValidateBlitFramebufferParameters(const Context *context,
1309                                        GLint srcX0,
1310                                        GLint srcY0,
1311                                        GLint srcX1,
1312                                        GLint srcY1,
1313                                        GLint dstX0,
1314                                        GLint dstY0,
1315                                        GLint dstX1,
1316                                        GLint dstY1,
1317                                        GLbitfield mask,
1318                                        GLenum filter)
1319 {
1320     switch (filter)
1321     {
1322         case GL_NEAREST:
1323             break;
1324         case GL_LINEAR:
1325             break;
1326         default:
1327             context->validationError(GL_INVALID_ENUM, kBlitInvalidFilter);
1328             return false;
1329     }
1330 
1331     if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1332     {
1333         context->validationError(GL_INVALID_VALUE, kBlitInvalidMask);
1334         return false;
1335     }
1336 
1337     // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1338     // color buffer, leaving only nearest being unfiltered from above
1339     if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1340     {
1341         context->validationError(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
1342         return false;
1343     }
1344 
1345     const auto &glState          = context->getState();
1346     Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1347     Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1348 
1349     if (!readFramebuffer || !drawFramebuffer)
1350     {
1351         context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
1352         return false;
1353     }
1354 
1355     if (!ValidateFramebufferComplete(context, readFramebuffer))
1356     {
1357         return false;
1358     }
1359 
1360     if (!ValidateFramebufferComplete(context, drawFramebuffer))
1361     {
1362         return false;
1363     }
1364 
1365     // The draw and read framebuffers can only match if:
1366     // - They are the default framebuffer AND
1367     // - The read/draw surfaces are different
1368     if ((readFramebuffer->id() == drawFramebuffer->id()) &&
1369         ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
1370          (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
1371     {
1372         context->validationError(GL_INVALID_OPERATION, kBlitFeedbackLoop);
1373         return false;
1374     }
1375 
1376     // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
1377     // consider it MS. needResourceSamples = false
1378     if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer, false))
1379     {
1380         return false;
1381     }
1382 
1383     // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1384     // always run it in order to avoid triggering driver bugs.
1385     if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1386         DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1387     {
1388         context->validationError(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
1389         return false;
1390     }
1391 
1392     bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1393 
1394     if (mask & GL_COLOR_BUFFER_BIT)
1395     {
1396         const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
1397         const Extensions &extensions                 = context->getExtensions();
1398 
1399         if (readColorBuffer)
1400         {
1401             const Format &readFormat = readColorBuffer->getFormat();
1402 
1403             for (size_t drawbufferIdx = 0;
1404                  drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
1405             {
1406                 const FramebufferAttachment *attachment =
1407                     drawFramebuffer->getDrawBuffer(drawbufferIdx);
1408                 if (attachment)
1409                 {
1410                     const Format &drawFormat = attachment->getFormat();
1411 
1412                     // The GL ES 3.0.2 spec (pg 193) states that:
1413                     // 1) If the read buffer is fixed point format, the draw buffer must be as well
1414                     // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1415                     // as well
1416                     // 3) If the read buffer is a signed integer format, the draw buffer must be as
1417                     // well
1418                     // Changes with EXT_color_buffer_float:
1419                     // Case 1) is changed to fixed point OR floating point
1420                     GLenum readComponentType = readFormat.info->componentType;
1421                     GLenum drawComponentType = drawFormat.info->componentType;
1422                     bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1423                                            readComponentType == GL_SIGNED_NORMALIZED);
1424                     bool drawFixedPoint      = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1425                                            drawComponentType == GL_SIGNED_NORMALIZED);
1426 
1427                     if (extensions.colorBufferFloat)
1428                     {
1429                         bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1430                         bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1431 
1432                         if (readFixedOrFloat != drawFixedOrFloat)
1433                         {
1434                             context->validationError(GL_INVALID_OPERATION,
1435                                                      kBlitTypeMismatchFixedOrFloat);
1436                             return false;
1437                         }
1438                     }
1439                     else if (readFixedPoint != drawFixedPoint)
1440                     {
1441                         context->validationError(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
1442                         return false;
1443                     }
1444 
1445                     if (readComponentType == GL_UNSIGNED_INT &&
1446                         drawComponentType != GL_UNSIGNED_INT)
1447                     {
1448                         context->validationError(GL_INVALID_OPERATION,
1449                                                  kBlitTypeMismatchUnsignedInteger);
1450                         return false;
1451                     }
1452 
1453                     if (readComponentType == GL_INT && drawComponentType != GL_INT)
1454                     {
1455                         context->validationError(GL_INVALID_OPERATION,
1456                                                  kBlitTypeMismatchSignedInteger);
1457                         return false;
1458                     }
1459 
1460                     if (readColorBuffer->getSamples() > 0 &&
1461                         (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
1462                     {
1463                         context->validationError(GL_INVALID_OPERATION,
1464                                                  kBlitMultisampledFormatOrBoundsMismatch);
1465                         return false;
1466                     }
1467 
1468                     if (context->getExtensions().webglCompatibility &&
1469                         *readColorBuffer == *attachment)
1470                     {
1471                         context->validationError(GL_INVALID_OPERATION, kBlitSameImageColor);
1472                         return false;
1473                     }
1474                 }
1475             }
1476 
1477             if (readFormat.info->isInt() && filter == GL_LINEAR)
1478             {
1479                 context->validationError(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
1480                 return false;
1481             }
1482         }
1483         // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1484         // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1485         // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1486         // situation is an application error that would lead to a crash in ANGLE.
1487         else if (drawFramebuffer->hasEnabledDrawBuffer())
1488         {
1489             context->validationError(GL_INVALID_OPERATION, kBlitMissingColor);
1490             return false;
1491         }
1492     }
1493 
1494     GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1495     GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1496     for (size_t i = 0; i < 2; i++)
1497     {
1498         if (mask & masks[i])
1499         {
1500             const FramebufferAttachment *readBuffer =
1501                 readFramebuffer->getAttachment(context, attachments[i]);
1502             const FramebufferAttachment *drawBuffer =
1503                 drawFramebuffer->getAttachment(context, attachments[i]);
1504 
1505             if (readBuffer && drawBuffer)
1506             {
1507                 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
1508                 {
1509                     context->validationError(GL_INVALID_OPERATION,
1510                                              kBlitDepthOrStencilFormatMismatch);
1511                     return false;
1512                 }
1513 
1514                 if (readBuffer->getSamples() > 0 && !sameBounds)
1515                 {
1516                     context->validationError(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
1517                     return false;
1518                 }
1519 
1520                 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1521                 {
1522                     context->validationError(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
1523                     return false;
1524                 }
1525             }
1526             // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1527             else if (drawBuffer)
1528             {
1529                 context->validationError(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
1530                 return false;
1531             }
1532         }
1533     }
1534 
1535     // OVR_multiview2:
1536     // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1537     // current draw framebuffer isMultiview() or the number of
1538     // views in the current read framebuffer is more than one.
1539     if (readFramebuffer->readDisallowedByMultiview())
1540     {
1541         context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
1542         return false;
1543     }
1544     if (drawFramebuffer->isMultiview())
1545     {
1546         context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
1547         return false;
1548     }
1549 
1550     return true;
1551 }
1552 
ValidateReadPixelsRobustANGLE(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const GLsizei * length,const GLsizei * columns,const GLsizei * rows,const void * pixels)1553 bool ValidateReadPixelsRobustANGLE(const Context *context,
1554                                    GLint x,
1555                                    GLint y,
1556                                    GLsizei width,
1557                                    GLsizei height,
1558                                    GLenum format,
1559                                    GLenum type,
1560                                    GLsizei bufSize,
1561                                    const GLsizei *length,
1562                                    const GLsizei *columns,
1563                                    const GLsizei *rows,
1564                                    const void *pixels)
1565 {
1566     if (!ValidateRobustEntryPoint(context, bufSize))
1567     {
1568         return false;
1569     }
1570 
1571     GLsizei writeLength  = 0;
1572     GLsizei writeColumns = 0;
1573     GLsizei writeRows    = 0;
1574 
1575     if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1576                                 &writeColumns, &writeRows, pixels))
1577     {
1578         return false;
1579     }
1580 
1581     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
1582     {
1583         return false;
1584     }
1585 
1586     SetRobustLengthParam(length, writeLength);
1587     SetRobustLengthParam(columns, writeColumns);
1588     SetRobustLengthParam(rows, writeRows);
1589 
1590     return true;
1591 }
1592 
ValidateReadnPixelsEXT(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1593 bool ValidateReadnPixelsEXT(const Context *context,
1594                             GLint x,
1595                             GLint y,
1596                             GLsizei width,
1597                             GLsizei height,
1598                             GLenum format,
1599                             GLenum type,
1600                             GLsizei bufSize,
1601                             const void *pixels)
1602 {
1603     if (bufSize < 0)
1604     {
1605         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
1606         return false;
1607     }
1608 
1609     return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1610                                   nullptr, nullptr, pixels);
1611 }
1612 
ValidateReadnPixelsRobustANGLE(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const GLsizei * length,const GLsizei * columns,const GLsizei * rows,const void * data)1613 bool ValidateReadnPixelsRobustANGLE(const Context *context,
1614                                     GLint x,
1615                                     GLint y,
1616                                     GLsizei width,
1617                                     GLsizei height,
1618                                     GLenum format,
1619                                     GLenum type,
1620                                     GLsizei bufSize,
1621                                     const GLsizei *length,
1622                                     const GLsizei *columns,
1623                                     const GLsizei *rows,
1624                                     const void *data)
1625 {
1626     GLsizei writeLength  = 0;
1627     GLsizei writeColumns = 0;
1628     GLsizei writeRows    = 0;
1629 
1630     if (!ValidateRobustEntryPoint(context, bufSize))
1631     {
1632         return false;
1633     }
1634 
1635     if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1636                                 &writeColumns, &writeRows, data))
1637     {
1638         return false;
1639     }
1640 
1641     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
1642     {
1643         return false;
1644     }
1645 
1646     SetRobustLengthParam(length, writeLength);
1647     SetRobustLengthParam(columns, writeColumns);
1648     SetRobustLengthParam(rows, writeRows);
1649 
1650     return true;
1651 }
1652 
ValidateGenQueriesEXT(const Context * context,GLsizei n,const QueryID * ids)1653 bool ValidateGenQueriesEXT(const Context *context, GLsizei n, const QueryID *ids)
1654 {
1655     if (!context->getExtensions().occlusionQueryBoolean &&
1656         !context->getExtensions().disjointTimerQuery)
1657     {
1658         context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1659         return false;
1660     }
1661 
1662     return ValidateGenOrDelete(context, n);
1663 }
1664 
ValidateDeleteQueriesEXT(const Context * context,GLsizei n,const QueryID * ids)1665 bool ValidateDeleteQueriesEXT(const Context *context, GLsizei n, const QueryID *ids)
1666 {
1667     if (!context->getExtensions().occlusionQueryBoolean &&
1668         !context->getExtensions().disjointTimerQuery)
1669     {
1670         context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1671         return false;
1672     }
1673 
1674     return ValidateGenOrDelete(context, n);
1675 }
1676 
ValidateIsQueryEXT(const Context * context,QueryID id)1677 bool ValidateIsQueryEXT(const Context *context, QueryID id)
1678 {
1679     if (!context->getExtensions().occlusionQueryBoolean &&
1680         !context->getExtensions().disjointTimerQuery)
1681     {
1682         context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1683         return false;
1684     }
1685 
1686     return true;
1687 }
1688 
ValidateBeginQueryBase(const Context * context,QueryType target,QueryID id)1689 bool ValidateBeginQueryBase(const Context *context, QueryType target, QueryID id)
1690 {
1691     if (!ValidQueryType(context, target))
1692     {
1693         context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1694         return false;
1695     }
1696 
1697     if (id.value == 0)
1698     {
1699         context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1700         return false;
1701     }
1702 
1703     // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1704     // of zero, if the active query object name for <target> is non-zero (for the
1705     // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1706     // the active query for either target is non-zero), if <id> is the name of an
1707     // existing query object whose type does not match <target>, or if <id> is the
1708     // active query object name for any query type, the error INVALID_OPERATION is
1709     // generated.
1710 
1711     // Ensure no other queries are active
1712     // NOTE: If other queries than occlusion are supported, we will need to check
1713     // separately that:
1714     //    a) The query ID passed is not the current active query for any target/type
1715     //    b) There are no active queries for the requested target (and in the case
1716     //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1717     //       no query may be active for either if glBeginQuery targets either.
1718 
1719     if (context->getState().isQueryActive(target))
1720     {
1721         context->validationError(GL_INVALID_OPERATION, kOtherQueryActive);
1722         return false;
1723     }
1724 
1725     // check that name was obtained with glGenQueries
1726     if (!context->isQueryGenerated(id))
1727     {
1728         context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1729         return false;
1730     }
1731 
1732     // Check for type mismatch. If query is not yet started we're good to go.
1733     Query *queryObject = context->getQuery(id);
1734     if (queryObject && queryObject->getType() != target)
1735     {
1736         context->validationError(GL_INVALID_OPERATION, kQueryTargetMismatch);
1737         return false;
1738     }
1739 
1740     return true;
1741 }
1742 
ValidateBeginQueryEXT(const Context * context,QueryType target,QueryID id)1743 bool ValidateBeginQueryEXT(const Context *context, QueryType target, QueryID id)
1744 {
1745     if (!context->getExtensions().occlusionQueryBoolean &&
1746         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1747     {
1748         context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1749         return false;
1750     }
1751 
1752     return ValidateBeginQueryBase(context, target, id);
1753 }
1754 
ValidateEndQueryBase(const Context * context,QueryType target)1755 bool ValidateEndQueryBase(const Context *context, QueryType target)
1756 {
1757     if (!ValidQueryType(context, target))
1758     {
1759         context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1760         return false;
1761     }
1762 
1763     const Query *queryObject = context->getState().getActiveQuery(target);
1764 
1765     if (queryObject == nullptr)
1766     {
1767         context->validationError(GL_INVALID_OPERATION, kQueryInactive);
1768         return false;
1769     }
1770 
1771     return true;
1772 }
1773 
ValidateEndQueryEXT(const Context * context,QueryType target)1774 bool ValidateEndQueryEXT(const Context *context, QueryType target)
1775 {
1776     if (!context->getExtensions().occlusionQueryBoolean &&
1777         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1778     {
1779         context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1780         return false;
1781     }
1782 
1783     return ValidateEndQueryBase(context, target);
1784 }
1785 
ValidateQueryCounterEXT(const Context * context,QueryID id,QueryType target)1786 bool ValidateQueryCounterEXT(const Context *context, QueryID id, QueryType target)
1787 {
1788     if (!context->getExtensions().disjointTimerQuery)
1789     {
1790         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1791         return false;
1792     }
1793 
1794     if (target != QueryType::Timestamp)
1795     {
1796         context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
1797         return false;
1798     }
1799 
1800     if (!context->isQueryGenerated(id))
1801     {
1802         context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1803         return false;
1804     }
1805 
1806     // If query object is not started, that's fine.
1807     Query *queryObject = context->getQuery(id);
1808     if (queryObject && context->getState().isQueryActive(queryObject))
1809     {
1810         context->validationError(GL_INVALID_OPERATION, kQueryActive);
1811         return false;
1812     }
1813 
1814     return true;
1815 }
1816 
ValidateGetQueryivBase(const Context * context,QueryType target,GLenum pname,GLsizei * numParams)1817 bool ValidateGetQueryivBase(const Context *context,
1818                             QueryType target,
1819                             GLenum pname,
1820                             GLsizei *numParams)
1821 {
1822     if (numParams)
1823     {
1824         *numParams = 0;
1825     }
1826 
1827     if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
1828     {
1829         context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1830         return false;
1831     }
1832 
1833     switch (pname)
1834     {
1835         case GL_CURRENT_QUERY_EXT:
1836             if (target == QueryType::Timestamp)
1837             {
1838                 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
1839                 return false;
1840             }
1841             break;
1842         case GL_QUERY_COUNTER_BITS_EXT:
1843             if (!context->getExtensions().disjointTimerQuery ||
1844                 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
1845             {
1846                 context->validationError(GL_INVALID_ENUM, kInvalidPname);
1847                 return false;
1848             }
1849             break;
1850         default:
1851             context->validationError(GL_INVALID_ENUM, kInvalidPname);
1852             return false;
1853     }
1854 
1855     if (numParams)
1856     {
1857         // All queries return only one value
1858         *numParams = 1;
1859     }
1860 
1861     return true;
1862 }
1863 
ValidateGetQueryivEXT(const Context * context,QueryType target,GLenum pname,const GLint * params)1864 bool ValidateGetQueryivEXT(const Context *context,
1865                            QueryType target,
1866                            GLenum pname,
1867                            const GLint *params)
1868 {
1869     if (!context->getExtensions().occlusionQueryBoolean &&
1870         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1871     {
1872         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1873         return false;
1874     }
1875 
1876     return ValidateGetQueryivBase(context, target, pname, nullptr);
1877 }
1878 
ValidateGetQueryivRobustANGLE(const Context * context,QueryType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)1879 bool ValidateGetQueryivRobustANGLE(const Context *context,
1880                                    QueryType target,
1881                                    GLenum pname,
1882                                    GLsizei bufSize,
1883                                    const GLsizei *length,
1884                                    const GLint *params)
1885 {
1886     if (!ValidateRobustEntryPoint(context, bufSize))
1887     {
1888         return false;
1889     }
1890 
1891     GLsizei numParams = 0;
1892 
1893     if (!ValidateGetQueryivBase(context, target, pname, &numParams))
1894     {
1895         return false;
1896     }
1897 
1898     if (!ValidateRobustBufferSize(context, bufSize, numParams))
1899     {
1900         return false;
1901     }
1902 
1903     SetRobustLengthParam(length, numParams);
1904 
1905     return true;
1906 }
1907 
ValidateGetQueryObjectValueBase(const Context * context,QueryID id,GLenum pname,GLsizei * numParams)1908 bool ValidateGetQueryObjectValueBase(const Context *context,
1909                                      QueryID id,
1910                                      GLenum pname,
1911                                      GLsizei *numParams)
1912 {
1913     if (numParams)
1914     {
1915         *numParams = 1;
1916     }
1917 
1918     if (context->isContextLost())
1919     {
1920         context->validationError(GL_CONTEXT_LOST, kContextLost);
1921 
1922         if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
1923         {
1924             // Generate an error but still return true, the context still needs to return a
1925             // value in this case.
1926             return true;
1927         }
1928         else
1929         {
1930             return false;
1931         }
1932     }
1933 
1934     Query *queryObject = context->getQuery(id);
1935 
1936     if (!queryObject)
1937     {
1938         context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1939         return false;
1940     }
1941 
1942     if (context->getState().isQueryActive(queryObject))
1943     {
1944         context->validationError(GL_INVALID_OPERATION, kQueryActive);
1945         return false;
1946     }
1947 
1948     switch (pname)
1949     {
1950         case GL_QUERY_RESULT_EXT:
1951         case GL_QUERY_RESULT_AVAILABLE_EXT:
1952             break;
1953 
1954         default:
1955             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1956             return false;
1957     }
1958 
1959     return true;
1960 }
1961 
ValidateGetQueryObjectivEXT(const Context * context,QueryID id,GLenum pname,const GLint * params)1962 bool ValidateGetQueryObjectivEXT(const Context *context,
1963                                  QueryID id,
1964                                  GLenum pname,
1965                                  const GLint *params)
1966 {
1967     if (!context->getExtensions().disjointTimerQuery)
1968     {
1969         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1970         return false;
1971     }
1972     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1973 }
1974 
ValidateGetQueryObjectivRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)1975 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
1976                                          QueryID id,
1977                                          GLenum pname,
1978                                          GLsizei bufSize,
1979                                          const GLsizei *length,
1980                                          const GLint *params)
1981 {
1982     if (!context->getExtensions().disjointTimerQuery)
1983     {
1984         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1985         return false;
1986     }
1987 
1988     if (!ValidateRobustEntryPoint(context, bufSize))
1989     {
1990         return false;
1991     }
1992 
1993     GLsizei numParams = 0;
1994 
1995     if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
1996     {
1997         return false;
1998     }
1999 
2000     if (!ValidateRobustBufferSize(context, bufSize, numParams))
2001     {
2002         return false;
2003     }
2004 
2005     SetRobustLengthParam(length, numParams);
2006 
2007     return true;
2008 }
2009 
ValidateGetQueryObjectuivEXT(const Context * context,QueryID id,GLenum pname,const GLuint * params)2010 bool ValidateGetQueryObjectuivEXT(const Context *context,
2011                                   QueryID id,
2012                                   GLenum pname,
2013                                   const GLuint *params)
2014 {
2015     if (!context->getExtensions().disjointTimerQuery &&
2016         !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2017     {
2018         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2019         return false;
2020     }
2021     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2022 }
2023 
ValidateGetQueryObjectuivRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)2024 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
2025                                           QueryID id,
2026                                           GLenum pname,
2027                                           GLsizei bufSize,
2028                                           const GLsizei *length,
2029                                           const GLuint *params)
2030 {
2031     if (!context->getExtensions().disjointTimerQuery &&
2032         !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2033     {
2034         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2035         return false;
2036     }
2037 
2038     if (!ValidateRobustEntryPoint(context, bufSize))
2039     {
2040         return false;
2041     }
2042 
2043     GLsizei numParams = 0;
2044 
2045     if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2046     {
2047         return false;
2048     }
2049 
2050     if (!ValidateRobustBufferSize(context, bufSize, numParams))
2051     {
2052         return false;
2053     }
2054 
2055     SetRobustLengthParam(length, numParams);
2056 
2057     return true;
2058 }
2059 
ValidateGetQueryObjecti64vEXT(const Context * context,QueryID id,GLenum pname,GLint64 * params)2060 bool ValidateGetQueryObjecti64vEXT(const Context *context,
2061                                    QueryID id,
2062                                    GLenum pname,
2063                                    GLint64 *params)
2064 {
2065     if (!context->getExtensions().disjointTimerQuery)
2066     {
2067         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2068         return false;
2069     }
2070     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2071 }
2072 
ValidateGetQueryObjecti64vRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * params)2073 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
2074                                            QueryID id,
2075                                            GLenum pname,
2076                                            GLsizei bufSize,
2077                                            const GLsizei *length,
2078                                            GLint64 *params)
2079 {
2080     if (!context->getExtensions().disjointTimerQuery)
2081     {
2082         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2083         return false;
2084     }
2085 
2086     if (!ValidateRobustEntryPoint(context, bufSize))
2087     {
2088         return false;
2089     }
2090 
2091     GLsizei numParams = 0;
2092 
2093     if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2094     {
2095         return false;
2096     }
2097 
2098     if (!ValidateRobustBufferSize(context, bufSize, numParams))
2099     {
2100         return false;
2101     }
2102 
2103     SetRobustLengthParam(length, numParams);
2104 
2105     return true;
2106 }
2107 
ValidateGetQueryObjectui64vEXT(const Context * context,QueryID id,GLenum pname,GLuint64 * params)2108 bool ValidateGetQueryObjectui64vEXT(const Context *context,
2109                                     QueryID id,
2110                                     GLenum pname,
2111                                     GLuint64 *params)
2112 {
2113     if (!context->getExtensions().disjointTimerQuery)
2114     {
2115         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2116         return false;
2117     }
2118     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2119 }
2120 
ValidateGetQueryObjectui64vRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLuint64 * params)2121 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
2122                                             QueryID id,
2123                                             GLenum pname,
2124                                             GLsizei bufSize,
2125                                             const GLsizei *length,
2126                                             GLuint64 *params)
2127 {
2128     if (!context->getExtensions().disjointTimerQuery)
2129     {
2130         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2131         return false;
2132     }
2133 
2134     if (!ValidateRobustEntryPoint(context, bufSize))
2135     {
2136         return false;
2137     }
2138 
2139     GLsizei numParams = 0;
2140 
2141     if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2142     {
2143         return false;
2144     }
2145 
2146     if (!ValidateRobustBufferSize(context, bufSize, numParams))
2147     {
2148         return false;
2149     }
2150 
2151     SetRobustLengthParam(length, numParams);
2152 
2153     return true;
2154 }
2155 
ValidateUniformCommonBase(const Context * context,const Program * program,UniformLocation location,GLsizei count,const LinkedUniform ** uniformOut)2156 bool ValidateUniformCommonBase(const Context *context,
2157                                const Program *program,
2158                                UniformLocation location,
2159                                GLsizei count,
2160                                const LinkedUniform **uniformOut)
2161 {
2162     // TODO(Jiajia): Add image uniform check in future.
2163     if (count < 0)
2164     {
2165         context->validationError(GL_INVALID_VALUE, kNegativeCount);
2166         return false;
2167     }
2168 
2169     if (!program)
2170     {
2171         context->validationError(GL_INVALID_OPERATION, kInvalidProgramName);
2172         return false;
2173     }
2174 
2175     if (!program->isLinked())
2176     {
2177         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
2178         return false;
2179     }
2180 
2181     if (location.value == -1)
2182     {
2183         // Silently ignore the uniform command
2184         return false;
2185     }
2186 
2187     const auto &uniformLocations = program->getUniformLocations();
2188     size_t castedLocation        = static_cast<size_t>(location.value);
2189     if (castedLocation >= uniformLocations.size())
2190     {
2191         context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
2192         return false;
2193     }
2194 
2195     const auto &uniformLocation = uniformLocations[castedLocation];
2196     if (uniformLocation.ignored)
2197     {
2198         // Silently ignore the uniform command
2199         return false;
2200     }
2201 
2202     if (!uniformLocation.used())
2203     {
2204         context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
2205         return false;
2206     }
2207 
2208     const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2209 
2210     // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2211     if (count > 1 && !uniform.isArray())
2212     {
2213         context->validationError(GL_INVALID_OPERATION, kInvalidUniformCount);
2214         return false;
2215     }
2216 
2217     *uniformOut = &uniform;
2218     return true;
2219 }
2220 
ValidateUniform1ivValue(const Context * context,GLenum uniformType,GLsizei count,const GLint * value)2221 bool ValidateUniform1ivValue(const Context *context,
2222                              GLenum uniformType,
2223                              GLsizei count,
2224                              const GLint *value)
2225 {
2226     // Value type is GL_INT, because we only get here from glUniform1i{v}.
2227     // It is compatible with INT or BOOL.
2228     // Do these cheap tests first, for a little extra speed.
2229     if (GL_INT == uniformType || GL_BOOL == uniformType)
2230     {
2231         return true;
2232     }
2233 
2234     if (IsSamplerType(uniformType))
2235     {
2236         // Check that the values are in range.
2237         const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2238         for (GLsizei i = 0; i < count; ++i)
2239         {
2240             if (value[i] < 0 || value[i] >= max)
2241             {
2242                 context->validationError(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
2243                 return false;
2244             }
2245         }
2246         return true;
2247     }
2248 
2249     context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
2250     return false;
2251 }
2252 
ValidateUniformMatrixValue(const Context * context,GLenum valueType,GLenum uniformType)2253 bool ValidateUniformMatrixValue(const Context *context, GLenum valueType, GLenum uniformType)
2254 {
2255     // Check that the value type is compatible with uniform type.
2256     if (valueType == uniformType)
2257     {
2258         return true;
2259     }
2260 
2261     context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
2262     return false;
2263 }
2264 
ValidateUniform(const Context * context,GLenum valueType,UniformLocation location,GLsizei count)2265 bool ValidateUniform(const Context *context,
2266                      GLenum valueType,
2267                      UniformLocation location,
2268                      GLsizei count)
2269 {
2270     const LinkedUniform *uniform = nullptr;
2271     Program *programObject       = context->getActiveLinkedProgram();
2272     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2273            ValidateUniformValue(context, valueType, uniform->type);
2274 }
2275 
ValidateUniform1iv(const Context * context,UniformLocation location,GLsizei count,const GLint * value)2276 bool ValidateUniform1iv(const Context *context,
2277                         UniformLocation location,
2278                         GLsizei count,
2279                         const GLint *value)
2280 {
2281     const LinkedUniform *uniform = nullptr;
2282     Program *programObject       = context->getActiveLinkedProgram();
2283     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2284            ValidateUniform1ivValue(context, uniform->type, count, value);
2285 }
2286 
ValidateUniformMatrix(const Context * context,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)2287 bool ValidateUniformMatrix(const Context *context,
2288                            GLenum valueType,
2289                            UniformLocation location,
2290                            GLsizei count,
2291                            GLboolean transpose)
2292 {
2293     if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
2294     {
2295         context->validationError(GL_INVALID_VALUE, kES3Required);
2296         return false;
2297     }
2298 
2299     const LinkedUniform *uniform = nullptr;
2300     Program *programObject       = context->getActiveLinkedProgram();
2301     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2302            ValidateUniformMatrixValue(context, valueType, uniform->type);
2303 }
2304 
ValidateStateQuery(const Context * context,GLenum pname,GLenum * nativeType,unsigned int * numParams)2305 bool ValidateStateQuery(const Context *context,
2306                         GLenum pname,
2307                         GLenum *nativeType,
2308                         unsigned int *numParams)
2309 {
2310     if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2311     {
2312         context->validationError(GL_INVALID_ENUM, kInvalidPname);
2313         return false;
2314     }
2315 
2316     const Caps &caps = context->getCaps();
2317 
2318     if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2319     {
2320         int colorAttachment = (pname - GL_DRAW_BUFFER0);
2321 
2322         if (colorAttachment >= caps.maxDrawBuffers)
2323         {
2324             context->validationError(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
2325             return false;
2326         }
2327     }
2328 
2329     switch (pname)
2330     {
2331         case GL_TEXTURE_BINDING_2D:
2332         case GL_TEXTURE_BINDING_CUBE_MAP:
2333         case GL_TEXTURE_BINDING_3D:
2334         case GL_TEXTURE_BINDING_2D_ARRAY:
2335         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
2336             break;
2337         case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
2338             if (!context->getExtensions().textureStorageMultisample2DArrayOES)
2339             {
2340                 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
2341                 return false;
2342             }
2343             break;
2344         case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2345             if (!context->getExtensions().textureRectangle)
2346             {
2347                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2348                 return false;
2349             }
2350             break;
2351         case GL_TEXTURE_BINDING_EXTERNAL_OES:
2352             if (!context->getExtensions().eglStreamConsumerExternalNV &&
2353                 !context->getExtensions().eglImageExternalOES)
2354             {
2355                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2356                 return false;
2357             }
2358             break;
2359 
2360         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2361         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2362         {
2363             Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
2364             ASSERT(readFramebuffer);
2365 
2366             if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, readFramebuffer))
2367             {
2368                 return false;
2369             }
2370 
2371             if (readFramebuffer->getReadBufferState() == GL_NONE)
2372             {
2373                 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
2374                 return false;
2375             }
2376 
2377             const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
2378             if (!attachment)
2379             {
2380                 context->validationError(GL_INVALID_OPERATION, kReadBufferNotAttached);
2381                 return false;
2382             }
2383         }
2384         break;
2385 
2386         default:
2387             break;
2388     }
2389 
2390     // pname is valid, but there are no parameters to return
2391     if (*numParams == 0)
2392     {
2393         return false;
2394     }
2395 
2396     return true;
2397 }
2398 
ValidateGetBooleanvRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLboolean * params)2399 bool ValidateGetBooleanvRobustANGLE(const Context *context,
2400                                     GLenum pname,
2401                                     GLsizei bufSize,
2402                                     const GLsizei *length,
2403                                     const GLboolean *params)
2404 {
2405     GLenum nativeType;
2406     unsigned int numParams = 0;
2407 
2408     if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2409     {
2410         return false;
2411     }
2412 
2413     SetRobustLengthParam(length, numParams);
2414 
2415     return true;
2416 }
2417 
ValidateGetFloatvRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)2418 bool ValidateGetFloatvRobustANGLE(const Context *context,
2419                                   GLenum pname,
2420                                   GLsizei bufSize,
2421                                   const GLsizei *length,
2422                                   const GLfloat *params)
2423 {
2424     GLenum nativeType;
2425     unsigned int numParams = 0;
2426 
2427     if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2428     {
2429         return false;
2430     }
2431 
2432     SetRobustLengthParam(length, numParams);
2433 
2434     return true;
2435 }
2436 
ValidateGetIntegervRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * data)2437 bool ValidateGetIntegervRobustANGLE(const Context *context,
2438                                     GLenum pname,
2439                                     GLsizei bufSize,
2440                                     const GLsizei *length,
2441                                     const GLint *data)
2442 {
2443     GLenum nativeType;
2444     unsigned int numParams = 0;
2445 
2446     if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2447     {
2448         return false;
2449     }
2450 
2451     SetRobustLengthParam(length, numParams);
2452 
2453     return true;
2454 }
2455 
ValidateGetInteger64vRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * data)2456 bool ValidateGetInteger64vRobustANGLE(const Context *context,
2457                                       GLenum pname,
2458                                       GLsizei bufSize,
2459                                       const GLsizei *length,
2460                                       GLint64 *data)
2461 {
2462     GLenum nativeType;
2463     unsigned int numParams = 0;
2464 
2465     if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2466     {
2467         return false;
2468     }
2469 
2470     if (nativeType == GL_INT_64_ANGLEX)
2471     {
2472         CastStateValues(context, nativeType, pname, numParams, data);
2473         return false;
2474     }
2475 
2476     SetRobustLengthParam(length, numParams);
2477     return true;
2478 }
2479 
ValidateRobustStateQuery(const Context * context,GLenum pname,GLsizei bufSize,GLenum * nativeType,unsigned int * numParams)2480 bool ValidateRobustStateQuery(const Context *context,
2481                               GLenum pname,
2482                               GLsizei bufSize,
2483                               GLenum *nativeType,
2484                               unsigned int *numParams)
2485 {
2486     if (!ValidateRobustEntryPoint(context, bufSize))
2487     {
2488         return false;
2489     }
2490 
2491     if (!ValidateStateQuery(context, pname, nativeType, numParams))
2492     {
2493         return false;
2494     }
2495 
2496     if (!ValidateRobustBufferSize(context, bufSize, *numParams))
2497     {
2498         return false;
2499     }
2500 
2501     return true;
2502 }
2503 
ValidateCopyTexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border,Format * textureFormatOut)2504 bool ValidateCopyTexImageParametersBase(const Context *context,
2505                                         TextureTarget target,
2506                                         GLint level,
2507                                         GLenum internalformat,
2508                                         bool isSubImage,
2509                                         GLint xoffset,
2510                                         GLint yoffset,
2511                                         GLint zoffset,
2512                                         GLint x,
2513                                         GLint y,
2514                                         GLsizei width,
2515                                         GLsizei height,
2516                                         GLint border,
2517                                         Format *textureFormatOut)
2518 {
2519     TextureType texType = TextureTargetToType(target);
2520 
2521     if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2522     {
2523         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
2524         return false;
2525     }
2526 
2527     if (width < 0 || height < 0)
2528     {
2529         context->validationError(GL_INVALID_VALUE, kNegativeSize);
2530         return false;
2531     }
2532 
2533     if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2534         std::numeric_limits<GLsizei>::max() - yoffset < height)
2535     {
2536         context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
2537         return false;
2538     }
2539 
2540     if (border != 0)
2541     {
2542         context->validationError(GL_INVALID_VALUE, kInvalidBorder);
2543         return false;
2544     }
2545 
2546     if (!ValidMipLevel(context, texType, level))
2547     {
2548         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
2549         return false;
2550     }
2551 
2552     const State &state           = context->getState();
2553     Framebuffer *readFramebuffer = state.getReadFramebuffer();
2554     if (!ValidateFramebufferComplete(context, readFramebuffer))
2555     {
2556         return false;
2557     }
2558 
2559     // needResourceSamples = true. Treat renderToTexture textures as single sample since they will
2560     // be resolved before copying
2561     if (!readFramebuffer->isDefault() &&
2562         !ValidateFramebufferNotMultisampled(context, readFramebuffer, true))
2563     {
2564         return false;
2565     }
2566 
2567     if (readFramebuffer->getReadBufferState() == GL_NONE)
2568     {
2569         context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
2570         return false;
2571     }
2572 
2573     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2574     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
2575     // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2576     // situation is an application error that would lead to a crash in ANGLE.
2577     const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
2578     if (source == nullptr)
2579     {
2580         context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
2581         return false;
2582     }
2583 
2584     // ANGLE_multiview spec, Revision 1:
2585     // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2586     // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2587     // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2588     // framebuffer is more than one.
2589     if (readFramebuffer->readDisallowedByMultiview())
2590     {
2591         context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
2592         return false;
2593     }
2594 
2595     const Caps &caps = context->getCaps();
2596 
2597     GLint maxDimension = 0;
2598     switch (texType)
2599     {
2600         case TextureType::_2D:
2601             maxDimension = caps.max2DTextureSize;
2602             break;
2603 
2604         case TextureType::CubeMap:
2605             maxDimension = caps.maxCubeMapTextureSize;
2606             break;
2607 
2608         case TextureType::Rectangle:
2609             maxDimension = caps.maxRectangleTextureSize;
2610             break;
2611 
2612         case TextureType::_2DArray:
2613             maxDimension = caps.max2DTextureSize;
2614             break;
2615 
2616         case TextureType::_3D:
2617             maxDimension = caps.max3DTextureSize;
2618             break;
2619 
2620         default:
2621             context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
2622             return false;
2623     }
2624 
2625     Texture *texture = state.getTargetTexture(texType);
2626     if (!texture)
2627     {
2628         context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
2629         return false;
2630     }
2631 
2632     if (texture->getImmutableFormat() && !isSubImage)
2633     {
2634         context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
2635         return false;
2636     }
2637 
2638     const InternalFormat &formatInfo =
2639         isSubImage ? *texture->getFormat(target, level).info
2640                    : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
2641 
2642     if (formatInfo.depthBits > 0 || formatInfo.compressed)
2643     {
2644         context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
2645         return false;
2646     }
2647 
2648     if (isSubImage)
2649     {
2650         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2651             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2652             static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
2653         {
2654             context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
2655             return false;
2656         }
2657     }
2658     else
2659     {
2660         if (texType == TextureType::CubeMap && width != height)
2661         {
2662             context->validationError(GL_INVALID_VALUE, kCubemapIncomplete);
2663             return false;
2664         }
2665 
2666         if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
2667         {
2668             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2669             return false;
2670         }
2671 
2672         int maxLevelDimension = (maxDimension >> level);
2673         if (static_cast<int>(width) > maxLevelDimension ||
2674             static_cast<int>(height) > maxLevelDimension)
2675         {
2676             context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
2677             return false;
2678         }
2679     }
2680 
2681     if (textureFormatOut)
2682     {
2683         *textureFormatOut = texture->getFormat(target, level);
2684     }
2685 
2686     // Detect texture copying feedback loops for WebGL.
2687     if (context->getExtensions().webglCompatibility)
2688     {
2689         if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
2690         {
2691             context->validationError(GL_INVALID_OPERATION, kFeedbackLoop);
2692             return false;
2693         }
2694     }
2695 
2696     return true;
2697 }
2698 
ValidateProgramDrawStates(const State & state,const Extensions & extensions,Program * program)2699 const char *ValidateProgramDrawStates(const State &state,
2700                                       const Extensions &extensions,
2701                                       Program *program)
2702 {
2703     if (extensions.multiview || extensions.multiview2)
2704     {
2705         const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
2706         Framebuffer *framebuffer      = state.getDrawFramebuffer();
2707         const int framebufferNumViews = framebuffer->getNumViews();
2708 
2709         if (framebufferNumViews != programNumViews)
2710         {
2711             return gl::err::kMultiviewMismatch;
2712         }
2713 
2714         if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
2715         {
2716             return gl::err::kMultiviewTransformFeedback;
2717         }
2718 
2719         if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2720             state.isQueryActive(QueryType::TimeElapsed))
2721         {
2722             return gl::err::kMultiviewTimerQuery;
2723         }
2724     }
2725 
2726     // Uniform buffer validation
2727     for (unsigned int uniformBlockIndex = 0;
2728          uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2729     {
2730         const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2731         GLuint blockBinding                = program->getUniformBlockBinding(uniformBlockIndex);
2732         const OffsetBindingPointer<Buffer> &uniformBuffer =
2733             state.getIndexedUniformBuffer(blockBinding);
2734 
2735         if (uniformBuffer.get() == nullptr)
2736         {
2737             // undefined behaviour
2738             return gl::err::kUniformBufferUnbound;
2739         }
2740 
2741         size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2742         if (uniformBufferSize < uniformBlock.dataSize)
2743         {
2744             // undefined behaviour
2745             return gl::err::kUniformBufferTooSmall;
2746         }
2747 
2748         if (extensions.webglCompatibility &&
2749             uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2750         {
2751             return gl::err::kUniformBufferBoundForTransformFeedback;
2752         }
2753     }
2754 
2755     return nullptr;
2756 }
2757 
ValidateProgramPipelineDrawStates(const State & state,const Extensions & extensions,ProgramPipeline * programPipeline)2758 const char *ValidateProgramPipelineDrawStates(const State &state,
2759                                               const Extensions &extensions,
2760                                               ProgramPipeline *programPipeline)
2761 {
2762     for (const ShaderType shaderType : gl::AllShaderTypes())
2763     {
2764         Program *program = programPipeline->getShaderProgram(shaderType);
2765         if (program)
2766         {
2767             const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
2768             if (errorMsg)
2769             {
2770                 return errorMsg;
2771             }
2772         }
2773     }
2774 
2775     return nullptr;
2776 }
2777 
ValidateProgramPipelineAttachedPrograms(ProgramPipeline * programPipeline)2778 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
2779 {
2780     // An INVALID_OPERATION error is generated by any command that transfers vertices to the
2781     // GL or launches compute work if the current set of active
2782     // program objects cannot be executed, for reasons including:
2783     // - A program object is active for at least one, but not all of the shader
2784     // stages that were present when the program was linked.
2785     for (const ShaderType shaderType : gl::AllShaderTypes())
2786     {
2787         Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
2788         if (shaderProgram)
2789         {
2790             ProgramExecutable &executable = shaderProgram->getExecutable();
2791             for (const ShaderType programShaderType : executable.getLinkedShaderStages())
2792             {
2793                 if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
2794                 {
2795                     return gl::err::kNotAllStagesOfSeparableProgramUsed;
2796                 }
2797             }
2798         }
2799     }
2800 
2801     return nullptr;
2802 }
2803 
2804 // Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2805 // completeness check.
ValidateDrawStates(const Context * context)2806 const char *ValidateDrawStates(const Context *context)
2807 {
2808     const Extensions &extensions = context->getExtensions();
2809     const State &state           = context->getState();
2810 
2811     // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2812     // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2813     // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2814     VertexArray *vertexArray = state.getVertexArray();
2815     ASSERT(vertexArray);
2816 
2817     if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
2818     {
2819         return kBufferMapped;
2820     }
2821 
2822     // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2823     // Section 6.10 of the WebGL 1.0 spec.
2824     Framebuffer *framebuffer = state.getDrawFramebuffer();
2825     ASSERT(framebuffer);
2826 
2827     if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2828     {
2829         ASSERT(framebuffer);
2830         const FramebufferAttachment *dsAttachment =
2831             framebuffer->getStencilOrDepthStencilAttachment();
2832         const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2833         ASSERT(stencilBits <= 8);
2834 
2835         const DepthStencilState &depthStencilState = state.getDepthStencilState();
2836         if (depthStencilState.stencilTest && stencilBits > 0)
2837         {
2838             GLuint maxStencilValue = (1 << stencilBits) - 1;
2839 
2840             bool differentRefs =
2841                 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2842                 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2843             bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2844                                        (depthStencilState.stencilBackWritemask & maxStencilValue);
2845             bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2846                                   (depthStencilState.stencilBackMask & maxStencilValue);
2847 
2848             if (differentRefs || differentWritemasks || differentMasks)
2849             {
2850                 if (!extensions.webglCompatibility)
2851                 {
2852                     WARN() << "This ANGLE implementation does not support separate front/back "
2853                               "stencil writemasks, reference values, or stencil mask values.";
2854                 }
2855                 return kStencilReferenceMaskOrMismatch;
2856             }
2857         }
2858     }
2859 
2860     if (!extensions.floatBlend)
2861     {
2862         const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
2863             state.getBlendEnabledDrawBufferMask() &
2864             framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
2865         if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
2866         {
2867             return kUnsupportedFloatBlending;
2868         }
2869     }
2870 
2871     if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
2872         extensions.webglCompatibility)
2873     {
2874         if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
2875         {
2876             if (extensions.webglCompatibility)
2877             {
2878                 return kInvalidConstantColor;
2879             }
2880 
2881             WARN() << kConstantColorAlphaLimitation;
2882             return kConstantColorAlphaLimitation;
2883         }
2884     }
2885 
2886     if (!framebuffer->isComplete(context))
2887     {
2888         // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2889         return kDrawFramebufferIncomplete;
2890     }
2891 
2892     if (context->getStateCache().hasAnyEnabledClientAttrib())
2893     {
2894         if (extensions.webglCompatibility || !state.areClientArraysEnabled())
2895         {
2896             // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2897             // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2898             // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2899             // to drawArrays or drawElements will generate an INVALID_OPERATION error.
2900             return kVertexArrayNoBuffer;
2901         }
2902 
2903         if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2904         {
2905             // This is an application error that would normally result in a crash, but we catch it
2906             // and return an error
2907             return kVertexArrayNoBufferPointer;
2908         }
2909     }
2910 
2911     // If we are running GLES1, there is no current program.
2912     if (context->getClientVersion() >= Version(2, 0))
2913     {
2914         Program *program                 = state.getLinkedProgram(context);
2915         ProgramPipeline *programPipeline = state.getProgramPipeline();
2916 
2917         if (program)
2918         {
2919             // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2920             // vertex shader stage or fragment shader stage is a undefined behaviour.
2921             // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2922             // produce undefined result.
2923             if (!program->getExecutable().hasLinkedShaderStage(ShaderType::Vertex) ||
2924                 !program->getExecutable().hasLinkedShaderStage(ShaderType::Fragment))
2925             {
2926                 return kNoActiveGraphicsShaderStage;
2927             }
2928 
2929             if (!program->validateSamplers(nullptr, context->getCaps()))
2930             {
2931                 return kTextureTypeConflict;
2932             }
2933 
2934             const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
2935             if (errorMsg)
2936             {
2937                 return errorMsg;
2938             }
2939         }
2940         else if (programPipeline)
2941         {
2942             // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2943             // vertex shader stage or fragment shader stage is a undefined behaviour.
2944             // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2945             // produce undefined result.
2946             if (!programPipeline->getExecutable().hasLinkedShaderStage(ShaderType::Vertex) ||
2947                 !programPipeline->getExecutable().hasLinkedShaderStage(ShaderType::Fragment))
2948             {
2949                 return kNoActiveGraphicsShaderStage;
2950             }
2951 
2952             const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
2953             if (errorMsg)
2954             {
2955                 return errorMsg;
2956             }
2957 
2958             if (!programPipeline->validateSamplers(nullptr, context->getCaps()))
2959             {
2960                 return kTextureTypeConflict;
2961             }
2962 
2963             errorMsg = ValidateProgramPipelineDrawStates(state, extensions, programPipeline);
2964             if (errorMsg)
2965             {
2966                 return errorMsg;
2967             }
2968         }
2969         else
2970         {
2971             return kProgramNotBound;
2972         }
2973 
2974         // Do some additional WebGL-specific validation
2975         if (extensions.webglCompatibility)
2976         {
2977             if (!state.validateSamplerFormats())
2978             {
2979                 return kSamplerFormatMismatch;
2980             }
2981 
2982             const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2983             if (state.isTransformFeedbackActive() &&
2984                 transformFeedbackObject->buffersBoundForOtherUse())
2985             {
2986                 return kTransformFeedbackBufferDoubleBound;
2987             }
2988 
2989             // Detect rendering feedback loops for WebGL.
2990             if (framebuffer->hasRenderingFeedbackLoop())
2991             {
2992                 return kFeedbackLoop;
2993             }
2994 
2995             // Detect that the vertex shader input types match the attribute types
2996             if (!ValidateVertexShaderAttributeTypeMatch(context))
2997             {
2998                 return kVertexShaderTypeMismatch;
2999             }
3000 
3001             if (!context->getState().getRasterizerState().rasterizerDiscard &&
3002                 !context->getState().allActiveDrawBufferChannelsMasked())
3003             {
3004                 // Detect that if there's active color buffer without fragment shader output
3005                 if (!ValidateFragmentShaderColorBufferMaskMatch(context))
3006                 {
3007                     return kDrawBufferMaskMismatch;
3008                 }
3009 
3010                 // Detect that the color buffer types match the fragment shader output types
3011                 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
3012                 {
3013                     return kDrawBufferTypeMismatch;
3014                 }
3015             }
3016 
3017             const VertexArray *vao = context->getState().getVertexArray();
3018             if (vao->hasTransformFeedbackBindingConflict(context))
3019             {
3020                 return kVertexBufferBoundForTransformFeedback;
3021             }
3022         }
3023     }
3024 
3025     return nullptr;
3026 }
3027 
RecordDrawModeError(const Context * context,PrimitiveMode mode)3028 void RecordDrawModeError(const Context *context, PrimitiveMode mode)
3029 {
3030     const State &state                      = context->getState();
3031     TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
3032     if (state.isTransformFeedbackActiveUnpaused())
3033     {
3034         if (!ValidateTransformFeedbackPrimitiveMode(context,
3035                                                     curTransformFeedback->getPrimitiveMode(), mode))
3036         {
3037             context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
3038             return;
3039         }
3040     }
3041 
3042     const Extensions &extensions = context->getExtensions();
3043 
3044     switch (mode)
3045     {
3046         case PrimitiveMode::Points:
3047         case PrimitiveMode::Lines:
3048         case PrimitiveMode::LineLoop:
3049         case PrimitiveMode::LineStrip:
3050         case PrimitiveMode::Triangles:
3051         case PrimitiveMode::TriangleStrip:
3052         case PrimitiveMode::TriangleFan:
3053             break;
3054 
3055         case PrimitiveMode::LinesAdjacency:
3056         case PrimitiveMode::LineStripAdjacency:
3057         case PrimitiveMode::TrianglesAdjacency:
3058         case PrimitiveMode::TriangleStripAdjacency:
3059             if (!extensions.geometryShader)
3060             {
3061                 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
3062                 return;
3063             }
3064             break;
3065         default:
3066             context->validationError(GL_INVALID_ENUM, kInvalidDrawMode);
3067             return;
3068     }
3069 
3070     // If we are running GLES1, there is no current program.
3071     if (context->getClientVersion() >= Version(2, 0))
3072     {
3073         Program *program = context->getActiveLinkedProgram();
3074         ASSERT(program);
3075 
3076         // Do geometry shader specific validations
3077         if (program->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
3078         {
3079             if (!IsCompatibleDrawModeWithGeometryShader(
3080                     mode, program->getGeometryShaderInputPrimitiveType()))
3081             {
3082                 context->validationError(GL_INVALID_OPERATION,
3083                                          kIncompatibleDrawModeAgainstGeometryShader);
3084                 return;
3085             }
3086         }
3087     }
3088 
3089     // An error should be recorded.
3090     UNREACHABLE();
3091 }
3092 
ValidateDrawArraysInstancedANGLE(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)3093 bool ValidateDrawArraysInstancedANGLE(const Context *context,
3094                                       PrimitiveMode mode,
3095                                       GLint first,
3096                                       GLsizei count,
3097                                       GLsizei primcount)
3098 {
3099     if (!context->getExtensions().instancedArraysANGLE)
3100     {
3101         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3102         return false;
3103     }
3104 
3105     if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
3106     {
3107         return false;
3108     }
3109 
3110     return ValidateDrawInstancedANGLE(context);
3111 }
3112 
ValidateDrawArraysInstancedEXT(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)3113 bool ValidateDrawArraysInstancedEXT(const Context *context,
3114                                     PrimitiveMode mode,
3115                                     GLint first,
3116                                     GLsizei count,
3117                                     GLsizei primcount)
3118 {
3119     if (!context->getExtensions().instancedArraysEXT)
3120     {
3121         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3122         return false;
3123     }
3124 
3125     if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
3126     {
3127         return false;
3128     }
3129 
3130     return true;
3131 }
3132 
ValidateDrawElementsStates(const Context * context)3133 const char *ValidateDrawElementsStates(const Context *context)
3134 {
3135     const State &state = context->getState();
3136 
3137     if (context->getStateCache().isTransformFeedbackActiveUnpaused())
3138     {
3139         // EXT_geometry_shader allows transform feedback to work with all draw commands.
3140         // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
3141         if (!context->getExtensions().geometryShader)
3142         {
3143             // It is an invalid operation to call DrawElements, DrawRangeElements or
3144             // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3145             // 86)
3146             return kUnsupportedDrawModeForTransformFeedback;
3147         }
3148     }
3149 
3150     const VertexArray *vao     = state.getVertexArray();
3151     Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
3152 
3153     if (elementArrayBuffer)
3154     {
3155         if (context->getExtensions().webglCompatibility)
3156         {
3157             if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3158             {
3159                 return kElementArrayBufferBoundForTransformFeedback;
3160             }
3161         }
3162         else if (elementArrayBuffer->isMapped())
3163         {
3164             // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3165             // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
3166             // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3167             return kBufferMapped;
3168         }
3169     }
3170     else
3171     {
3172         // [WebGL 1.0] Section 6.2 No Client Side Arrays
3173         // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3174         // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3175         if (!context->getState().areClientArraysEnabled() ||
3176             context->getExtensions().webglCompatibility)
3177         {
3178             return kMustHaveElementArrayBinding;
3179         }
3180     }
3181 
3182     return nullptr;
3183 }
3184 
ValidateDrawElementsInstancedANGLE(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)3185 bool ValidateDrawElementsInstancedANGLE(const Context *context,
3186                                         PrimitiveMode mode,
3187                                         GLsizei count,
3188                                         DrawElementsType type,
3189                                         const void *indices,
3190                                         GLsizei primcount)
3191 {
3192     if (!context->getExtensions().instancedArraysANGLE)
3193     {
3194         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3195         return false;
3196     }
3197 
3198     if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
3199     {
3200         return false;
3201     }
3202 
3203     return ValidateDrawInstancedANGLE(context);
3204 }
3205 
ValidateDrawElementsInstancedEXT(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)3206 bool ValidateDrawElementsInstancedEXT(const Context *context,
3207                                       PrimitiveMode mode,
3208                                       GLsizei count,
3209                                       DrawElementsType type,
3210                                       const void *indices,
3211                                       GLsizei primcount)
3212 {
3213     if (!context->getExtensions().instancedArraysEXT)
3214     {
3215         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3216         return false;
3217     }
3218 
3219     if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
3220     {
3221         return false;
3222     }
3223 
3224     return true;
3225 }
3226 
ValidateFramebufferTextureBase(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level)3227 bool ValidateFramebufferTextureBase(const Context *context,
3228                                     GLenum target,
3229                                     GLenum attachment,
3230                                     TextureID texture,
3231                                     GLint level)
3232 {
3233     if (!ValidFramebufferTarget(context, target))
3234     {
3235         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
3236         return false;
3237     }
3238 
3239     if (!ValidateAttachmentTarget(context, attachment))
3240     {
3241         return false;
3242     }
3243 
3244     if (texture.value != 0)
3245     {
3246         Texture *tex = context->getTexture(texture);
3247 
3248         if (tex == nullptr)
3249         {
3250             context->validationError(GL_INVALID_OPERATION, kMissingTexture);
3251             return false;
3252         }
3253 
3254         if (level < 0)
3255         {
3256             context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3257             return false;
3258         }
3259     }
3260 
3261     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
3262     ASSERT(framebuffer);
3263 
3264     if (framebuffer->isDefault())
3265     {
3266         context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
3267         return false;
3268     }
3269 
3270     return true;
3271 }
3272 
ValidateGetUniformBase(const Context * context,ShaderProgramID program,UniformLocation location)3273 bool ValidateGetUniformBase(const Context *context,
3274                             ShaderProgramID program,
3275                             UniformLocation location)
3276 {
3277     if (program.value == 0)
3278     {
3279         context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
3280         return false;
3281     }
3282 
3283     Program *programObject = GetValidProgram(context, program);
3284     if (!programObject)
3285     {
3286         return false;
3287     }
3288 
3289     if (!programObject || !programObject->isLinked())
3290     {
3291         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
3292         return false;
3293     }
3294 
3295     if (!programObject->isValidUniformLocation(location))
3296     {
3297         context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
3298         return false;
3299     }
3300 
3301     return true;
3302 }
3303 
ValidateSizedGetUniform(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,GLsizei * length)3304 static bool ValidateSizedGetUniform(const Context *context,
3305                                     ShaderProgramID program,
3306                                     UniformLocation location,
3307                                     GLsizei bufSize,
3308                                     GLsizei *length)
3309 {
3310     if (length)
3311     {
3312         *length = 0;
3313     }
3314 
3315     if (!ValidateGetUniformBase(context, program, location))
3316     {
3317         return false;
3318     }
3319 
3320     if (bufSize < 0)
3321     {
3322         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
3323         return false;
3324     }
3325 
3326     Program *programObject = context->getProgramResolveLink(program);
3327     ASSERT(programObject);
3328 
3329     // sized queries -- ensure the provided buffer is large enough
3330     const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3331     size_t requiredBytes         = VariableExternalSize(uniform.type);
3332     if (static_cast<size_t>(bufSize) < requiredBytes)
3333     {
3334         context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
3335         return false;
3336     }
3337 
3338     if (length)
3339     {
3340         *length = VariableComponentCount(uniform.type);
3341     }
3342     return true;
3343 }
3344 
ValidateGetnUniformfvEXT(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLfloat * params)3345 bool ValidateGetnUniformfvEXT(const Context *context,
3346                               ShaderProgramID program,
3347                               UniformLocation location,
3348                               GLsizei bufSize,
3349                               const GLfloat *params)
3350 {
3351     return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3352 }
3353 
ValidateGetnUniformfvRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3354 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
3355                                       ShaderProgramID program,
3356                                       UniformLocation location,
3357                                       GLsizei bufSize,
3358                                       const GLsizei *length,
3359                                       const GLfloat *params)
3360 {
3361     UNIMPLEMENTED();
3362     return false;
3363 }
3364 
ValidateGetnUniformivEXT(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLint * params)3365 bool ValidateGetnUniformivEXT(const Context *context,
3366                               ShaderProgramID program,
3367                               UniformLocation location,
3368                               GLsizei bufSize,
3369                               const GLint *params)
3370 {
3371     return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3372 }
3373 
ValidateGetnUniformivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)3374 bool ValidateGetnUniformivRobustANGLE(const Context *context,
3375                                       ShaderProgramID program,
3376                                       UniformLocation location,
3377                                       GLsizei bufSize,
3378                                       const GLsizei *length,
3379                                       const GLint *params)
3380 {
3381     UNIMPLEMENTED();
3382     return false;
3383 }
3384 
ValidateGetnUniformuivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)3385 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
3386                                        ShaderProgramID program,
3387                                        UniformLocation location,
3388                                        GLsizei bufSize,
3389                                        const GLsizei *length,
3390                                        const GLuint *params)
3391 {
3392     UNIMPLEMENTED();
3393     return false;
3394 }
3395 
ValidateGetUniformfvRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3396 bool ValidateGetUniformfvRobustANGLE(const Context *context,
3397                                      ShaderProgramID program,
3398                                      UniformLocation location,
3399                                      GLsizei bufSize,
3400                                      const GLsizei *length,
3401                                      const GLfloat *params)
3402 {
3403     if (!ValidateRobustEntryPoint(context, bufSize))
3404     {
3405         return false;
3406     }
3407 
3408     GLsizei writeLength = 0;
3409 
3410     // bufSize is validated in ValidateSizedGetUniform
3411     if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3412     {
3413         return false;
3414     }
3415 
3416     SetRobustLengthParam(length, writeLength);
3417 
3418     return true;
3419 }
3420 
ValidateGetUniformivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)3421 bool ValidateGetUniformivRobustANGLE(const Context *context,
3422                                      ShaderProgramID program,
3423                                      UniformLocation location,
3424                                      GLsizei bufSize,
3425                                      const GLsizei *length,
3426                                      const GLint *params)
3427 {
3428     if (!ValidateRobustEntryPoint(context, bufSize))
3429     {
3430         return false;
3431     }
3432 
3433     GLsizei writeLength = 0;
3434 
3435     // bufSize is validated in ValidateSizedGetUniform
3436     if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3437     {
3438         return false;
3439     }
3440 
3441     SetRobustLengthParam(length, writeLength);
3442 
3443     return true;
3444 }
3445 
ValidateGetUniformuivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)3446 bool ValidateGetUniformuivRobustANGLE(const Context *context,
3447                                       ShaderProgramID program,
3448                                       UniformLocation location,
3449                                       GLsizei bufSize,
3450                                       const GLsizei *length,
3451                                       const GLuint *params)
3452 {
3453     if (!ValidateRobustEntryPoint(context, bufSize))
3454     {
3455         return false;
3456     }
3457 
3458     if (context->getClientMajorVersion() < 3)
3459     {
3460         context->validationError(GL_INVALID_OPERATION, kES3Required);
3461         return false;
3462     }
3463 
3464     GLsizei writeLength = 0;
3465 
3466     // bufSize is validated in ValidateSizedGetUniform
3467     if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3468     {
3469         return false;
3470     }
3471 
3472     SetRobustLengthParam(length, writeLength);
3473 
3474     return true;
3475 }
3476 
ValidateDiscardFramebufferBase(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,bool defaultFramebuffer)3477 bool ValidateDiscardFramebufferBase(const Context *context,
3478                                     GLenum target,
3479                                     GLsizei numAttachments,
3480                                     const GLenum *attachments,
3481                                     bool defaultFramebuffer)
3482 {
3483     if (numAttachments < 0)
3484     {
3485         context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
3486         return false;
3487     }
3488 
3489     for (GLsizei i = 0; i < numAttachments; ++i)
3490     {
3491         if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
3492         {
3493             if (defaultFramebuffer)
3494             {
3495                 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
3496                 return false;
3497             }
3498 
3499             if (attachments[i] >=
3500                 GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
3501             {
3502                 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
3503                 return false;
3504             }
3505         }
3506         else
3507         {
3508             switch (attachments[i])
3509             {
3510                 case GL_DEPTH_ATTACHMENT:
3511                 case GL_STENCIL_ATTACHMENT:
3512                 case GL_DEPTH_STENCIL_ATTACHMENT:
3513                     if (defaultFramebuffer)
3514                     {
3515                         context->validationError(GL_INVALID_ENUM,
3516                                                  kDefaultFramebufferInvalidAttachment);
3517                         return false;
3518                     }
3519                     break;
3520                 case GL_COLOR:
3521                 case GL_DEPTH:
3522                 case GL_STENCIL:
3523                     if (!defaultFramebuffer)
3524                     {
3525                         context->validationError(GL_INVALID_ENUM,
3526                                                  kDefaultFramebufferInvalidAttachment);
3527                         return false;
3528                     }
3529                     break;
3530                 default:
3531                     context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
3532                     return false;
3533             }
3534         }
3535     }
3536 
3537     return true;
3538 }
3539 
ValidateInsertEventMarkerEXT(const Context * context,GLsizei length,const char * marker)3540 bool ValidateInsertEventMarkerEXT(const Context *context, GLsizei length, const char *marker)
3541 {
3542     if (!context->getExtensions().debugMarker)
3543     {
3544         // The debug marker calls should not set error state
3545         // However, it seems reasonable to set an error state if the extension is not enabled
3546         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3547         return false;
3548     }
3549 
3550     // Note that debug marker calls must not set error state
3551     if (length < 0)
3552     {
3553         return false;
3554     }
3555 
3556     if (marker == nullptr)
3557     {
3558         return false;
3559     }
3560 
3561     return true;
3562 }
3563 
ValidatePushGroupMarkerEXT(const Context * context,GLsizei length,const char * marker)3564 bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker)
3565 {
3566     if (!context->getExtensions().debugMarker)
3567     {
3568         // The debug marker calls should not set error state
3569         // However, it seems reasonable to set an error state if the extension is not enabled
3570         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3571         return false;
3572     }
3573 
3574     // Note that debug marker calls must not set error state
3575     if (length < 0)
3576     {
3577         return false;
3578     }
3579 
3580     if (length > 0 && marker == nullptr)
3581     {
3582         return false;
3583     }
3584 
3585     return true;
3586 }
3587 
ValidateEGLImageTargetTexture2DOES(const Context * context,TextureType type,GLeglImageOES image)3588 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
3589                                         TextureType type,
3590                                         GLeglImageOES image)
3591 {
3592     if (!context->getExtensions().eglImageOES && !context->getExtensions().eglImageExternalOES)
3593     {
3594         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3595         return false;
3596     }
3597 
3598     switch (type)
3599     {
3600         case TextureType::_2D:
3601             if (!context->getExtensions().eglImageOES)
3602             {
3603                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3604             }
3605             break;
3606 
3607         case TextureType::External:
3608             if (!context->getExtensions().eglImageExternalOES)
3609             {
3610                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3611             }
3612             break;
3613 
3614         default:
3615             context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3616             return false;
3617     }
3618 
3619     egl::Image *imageObject = static_cast<egl::Image *>(image);
3620 
3621     ASSERT(context->getDisplay());
3622     if (!context->getDisplay()->isValidImage(imageObject))
3623     {
3624         context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
3625         return false;
3626     }
3627 
3628     if (imageObject->getSamples() > 0)
3629     {
3630         context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
3631         return false;
3632     }
3633 
3634     if (!imageObject->isTexturable(context))
3635     {
3636         context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
3637         return false;
3638     }
3639 
3640     return true;
3641 }
3642 
ValidateEGLImageTargetRenderbufferStorageOES(const Context * context,GLenum target,GLeglImageOES image)3643 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
3644                                                   GLenum target,
3645                                                   GLeglImageOES image)
3646 {
3647     if (!context->getExtensions().eglImageOES)
3648     {
3649         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3650         return false;
3651     }
3652 
3653     switch (target)
3654     {
3655         case GL_RENDERBUFFER:
3656             break;
3657 
3658         default:
3659             context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
3660             return false;
3661     }
3662 
3663     egl::Image *imageObject = static_cast<egl::Image *>(image);
3664 
3665     ASSERT(context->getDisplay());
3666     if (!context->getDisplay()->isValidImage(imageObject))
3667     {
3668         context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
3669         return false;
3670     }
3671 
3672     if (!imageObject->isRenderable(context))
3673     {
3674         context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
3675         return false;
3676     }
3677 
3678     return true;
3679 }
3680 
ValidateBindVertexArrayBase(const Context * context,VertexArrayID array)3681 bool ValidateBindVertexArrayBase(const Context *context, VertexArrayID array)
3682 {
3683     if (!context->isVertexArrayGenerated(array))
3684     {
3685         // The default VAO should always exist
3686         ASSERT(array.value != 0);
3687         context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
3688         return false;
3689     }
3690 
3691     return true;
3692 }
3693 
ValidateProgramBinaryBase(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)3694 bool ValidateProgramBinaryBase(const Context *context,
3695                                ShaderProgramID program,
3696                                GLenum binaryFormat,
3697                                const void *binary,
3698                                GLint length)
3699 {
3700     Program *programObject = GetValidProgram(context, program);
3701     if (programObject == nullptr)
3702     {
3703         return false;
3704     }
3705 
3706     const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3707     if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3708         programBinaryFormats.end())
3709     {
3710         context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
3711         return false;
3712     }
3713 
3714     if (context->hasActiveTransformFeedback(program))
3715     {
3716         // ES 3.0.4 section 2.15 page 91
3717         context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
3718         return false;
3719     }
3720 
3721     return true;
3722 }
3723 
ValidateGetProgramBinaryBase(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)3724 bool ValidateGetProgramBinaryBase(const Context *context,
3725                                   ShaderProgramID program,
3726                                   GLsizei bufSize,
3727                                   const GLsizei *length,
3728                                   const GLenum *binaryFormat,
3729                                   const void *binary)
3730 {
3731     Program *programObject = GetValidProgram(context, program);
3732     if (programObject == nullptr)
3733     {
3734         return false;
3735     }
3736 
3737     if (!programObject->isLinked())
3738     {
3739         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
3740         return false;
3741     }
3742 
3743     if (context->getCaps().programBinaryFormats.empty())
3744     {
3745         context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
3746         return false;
3747     }
3748 
3749     return true;
3750 }
3751 
ValidateDrawBuffersBase(const Context * context,GLsizei n,const GLenum * bufs)3752 bool ValidateDrawBuffersBase(const Context *context, GLsizei n, const GLenum *bufs)
3753 {
3754     // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3755     if (n < 0)
3756     {
3757         context->validationError(GL_INVALID_VALUE, kNegativeCount);
3758         return false;
3759     }
3760     if (n > context->getCaps().maxDrawBuffers)
3761     {
3762         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
3763         return false;
3764     }
3765 
3766     ASSERT(context->getState().getDrawFramebuffer());
3767     FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
3768     GLuint maxColorAttachment   = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3769 
3770     // This should come first before the check for the default frame buffer
3771     // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3772     // rather than INVALID_OPERATION
3773     for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3774     {
3775         const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3776 
3777         if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
3778             (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3779              bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
3780         {
3781             // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
3782             // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3783             // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3784             // 3.1 is still a bit ambiguous about the error, but future specs are
3785             // expected to clarify that GL_INVALID_ENUM is the correct error.
3786             context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
3787             return false;
3788         }
3789         else if (bufs[colorAttachment] >= maxColorAttachment)
3790         {
3791             context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
3792             return false;
3793         }
3794         else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3795                  frameBufferId.value != 0)
3796         {
3797             // INVALID_OPERATION-GL is bound to buffer and ith argument
3798             // is not COLOR_ATTACHMENTi or NONE
3799             context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
3800             return false;
3801         }
3802     }
3803 
3804     // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3805     // and n is not 1 or bufs is bound to value other than BACK and NONE
3806     if (frameBufferId.value == 0)
3807     {
3808         if (n != 1)
3809         {
3810             context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
3811             return false;
3812         }
3813 
3814         if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3815         {
3816             context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
3817             return false;
3818         }
3819     }
3820 
3821     return true;
3822 }
3823 
ValidateGetBufferPointervBase(const Context * context,BufferBinding target,GLenum pname,GLsizei * length,void * const * params)3824 bool ValidateGetBufferPointervBase(const Context *context,
3825                                    BufferBinding target,
3826                                    GLenum pname,
3827                                    GLsizei *length,
3828                                    void *const *params)
3829 {
3830     if (length)
3831     {
3832         *length = 0;
3833     }
3834 
3835     if (!context->isValidBufferBinding(target))
3836     {
3837         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3838         return false;
3839     }
3840 
3841     switch (pname)
3842     {
3843         case GL_BUFFER_MAP_POINTER:
3844             break;
3845 
3846         default:
3847             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3848             return false;
3849     }
3850 
3851     // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3852     // target bound to zero generate an INVALID_OPERATION error."
3853     // GLES 3.1 section 6.6 explicitly specifies this error.
3854     if (context->getState().getTargetBuffer(target) == nullptr)
3855     {
3856         context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
3857         return false;
3858     }
3859 
3860     if (length)
3861     {
3862         *length = 1;
3863     }
3864 
3865     return true;
3866 }
3867 
ValidateUnmapBufferBase(const Context * context,BufferBinding target)3868 bool ValidateUnmapBufferBase(const Context *context, BufferBinding target)
3869 {
3870     if (!context->isValidBufferBinding(target))
3871     {
3872         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3873         return false;
3874     }
3875 
3876     Buffer *buffer = context->getState().getTargetBuffer(target);
3877 
3878     if (buffer == nullptr || !buffer->isMapped())
3879     {
3880         context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
3881         return false;
3882     }
3883 
3884     return true;
3885 }
3886 
ValidateMapBufferRangeBase(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3887 bool ValidateMapBufferRangeBase(const Context *context,
3888                                 BufferBinding target,
3889                                 GLintptr offset,
3890                                 GLsizeiptr length,
3891                                 GLbitfield access)
3892 {
3893     if (!context->isValidBufferBinding(target))
3894     {
3895         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3896         return false;
3897     }
3898 
3899     if (offset < 0)
3900     {
3901         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3902         return false;
3903     }
3904 
3905     if (length < 0)
3906     {
3907         context->validationError(GL_INVALID_VALUE, kNegativeLength);
3908         return false;
3909     }
3910 
3911     Buffer *buffer = context->getState().getTargetBuffer(target);
3912 
3913     if (!buffer)
3914     {
3915         context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3916         return false;
3917     }
3918 
3919     // Check for buffer overflow
3920     CheckedNumeric<size_t> checkedOffset(offset);
3921     auto checkedSize = checkedOffset + length;
3922 
3923     if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
3924     {
3925         context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
3926         return false;
3927     }
3928 
3929     // Check for invalid bits in the mask
3930     GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3931                                GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3932                                GL_MAP_UNSYNCHRONIZED_BIT;
3933 
3934     if (access & ~(allAccessBits))
3935     {
3936         context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
3937         return false;
3938     }
3939 
3940     if (length == 0)
3941     {
3942         context->validationError(GL_INVALID_OPERATION, kLengthZero);
3943         return false;
3944     }
3945 
3946     if (buffer->isMapped())
3947     {
3948         context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
3949         return false;
3950     }
3951 
3952     // Check for invalid bit combinations
3953     if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3954     {
3955         context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
3956         return false;
3957     }
3958 
3959     GLbitfield writeOnlyBits =
3960         GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3961 
3962     if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3963     {
3964         context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
3965         return false;
3966     }
3967 
3968     if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3969     {
3970         context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
3971         return false;
3972     }
3973 
3974     return ValidateMapBufferBase(context, target);
3975 }
3976 
ValidateFlushMappedBufferRangeBase(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)3977 bool ValidateFlushMappedBufferRangeBase(const Context *context,
3978                                         BufferBinding target,
3979                                         GLintptr offset,
3980                                         GLsizeiptr length)
3981 {
3982     if (offset < 0)
3983     {
3984         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3985         return false;
3986     }
3987 
3988     if (length < 0)
3989     {
3990         context->validationError(GL_INVALID_VALUE, kNegativeLength);
3991         return false;
3992     }
3993 
3994     if (!context->isValidBufferBinding(target))
3995     {
3996         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3997         return false;
3998     }
3999 
4000     Buffer *buffer = context->getState().getTargetBuffer(target);
4001 
4002     if (buffer == nullptr)
4003     {
4004         context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
4005         return false;
4006     }
4007 
4008     if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4009     {
4010         context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
4011         return false;
4012     }
4013 
4014     // Check for buffer overflow
4015     CheckedNumeric<size_t> checkedOffset(offset);
4016     auto checkedSize = checkedOffset + length;
4017 
4018     if (!checkedSize.IsValid() ||
4019         checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
4020     {
4021         context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
4022         return false;
4023     }
4024 
4025     return true;
4026 }
4027 
ValidateGenOrDelete(const Context * context,GLint n)4028 bool ValidateGenOrDelete(const Context *context, GLint n)
4029 {
4030     if (n < 0)
4031     {
4032         context->validationError(GL_INVALID_VALUE, kNegativeCount);
4033         return false;
4034     }
4035     return true;
4036 }
4037 
ValidateRobustEntryPoint(const Context * context,GLsizei bufSize)4038 bool ValidateRobustEntryPoint(const Context *context, GLsizei bufSize)
4039 {
4040     if (!context->getExtensions().robustClientMemory)
4041     {
4042         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4043         return false;
4044     }
4045 
4046     if (bufSize < 0)
4047     {
4048         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4049         return false;
4050     }
4051 
4052     return true;
4053 }
4054 
ValidateRobustBufferSize(const Context * context,GLsizei bufSize,GLsizei numParams)4055 bool ValidateRobustBufferSize(const Context *context, GLsizei bufSize, GLsizei numParams)
4056 {
4057     if (bufSize < numParams)
4058     {
4059         context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
4060         return false;
4061     }
4062 
4063     return true;
4064 }
4065 
ValidateGetFramebufferAttachmentParameterivBase(const Context * context,GLenum target,GLenum attachment,GLenum pname,GLsizei * numParams)4066 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
4067                                                      GLenum target,
4068                                                      GLenum attachment,
4069                                                      GLenum pname,
4070                                                      GLsizei *numParams)
4071 {
4072     if (!ValidFramebufferTarget(context, target))
4073     {
4074         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
4075         return false;
4076     }
4077 
4078     int clientVersion = context->getClientMajorVersion();
4079 
4080     switch (pname)
4081     {
4082         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4083         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4084         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4085         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4086             break;
4087 
4088         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
4089         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
4090             if (clientVersion < 3 ||
4091                 !(context->getExtensions().multiview || context->getExtensions().multiview2))
4092             {
4093                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4094                 return false;
4095             }
4096             break;
4097 
4098         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4099             if (!context->getExtensions().multisampledRenderToTexture)
4100             {
4101                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4102                 return false;
4103             }
4104             break;
4105 
4106         case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4107             if (clientVersion < 3 && !context->getExtensions().sRGB)
4108             {
4109                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4110                 return false;
4111             }
4112             break;
4113 
4114         case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4115         case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4116         case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4117         case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4118         case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4119         case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4120         case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4121         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4122             if (clientVersion < 3)
4123             {
4124                 context->validationError(GL_INVALID_ENUM, kES3Required);
4125                 return false;
4126             }
4127             break;
4128 
4129         case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4130             if (!context->getExtensions().geometryShader)
4131             {
4132                 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4133                 return false;
4134             }
4135             break;
4136 
4137         default:
4138             context->validationError(GL_INVALID_ENUM, kInvalidPname);
4139             return false;
4140     }
4141 
4142     // Determine if the attachment is a valid enum
4143     switch (attachment)
4144     {
4145         case GL_BACK:
4146         case GL_DEPTH:
4147         case GL_STENCIL:
4148             if (clientVersion < 3)
4149             {
4150                 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4151                 return false;
4152             }
4153             break;
4154 
4155         case GL_DEPTH_STENCIL_ATTACHMENT:
4156             if (clientVersion < 3 && !context->isWebGL1())
4157             {
4158                 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4159                 return false;
4160             }
4161             break;
4162 
4163         case GL_COLOR_ATTACHMENT0:
4164         case GL_DEPTH_ATTACHMENT:
4165         case GL_STENCIL_ATTACHMENT:
4166             break;
4167 
4168         default:
4169             if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4170                 attachment < GL_COLOR_ATTACHMENT0_EXT ||
4171                 (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
4172                     static_cast<GLuint>(context->getCaps().maxColorAttachments))
4173             {
4174                 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4175                 return false;
4176             }
4177             break;
4178     }
4179 
4180     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
4181     ASSERT(framebuffer);
4182 
4183     if (framebuffer->isDefault())
4184     {
4185         if (clientVersion < 3)
4186         {
4187             context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
4188             return false;
4189         }
4190 
4191         switch (attachment)
4192         {
4193             case GL_BACK:
4194             case GL_DEPTH:
4195             case GL_STENCIL:
4196                 break;
4197 
4198             default:
4199                 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4200                 return false;
4201         }
4202     }
4203     else
4204     {
4205         if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4206         {
4207             // Valid attachment query
4208         }
4209         else
4210         {
4211             switch (attachment)
4212             {
4213                 case GL_DEPTH_ATTACHMENT:
4214                 case GL_STENCIL_ATTACHMENT:
4215                     break;
4216 
4217                 case GL_DEPTH_STENCIL_ATTACHMENT:
4218                     if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
4219                     {
4220                         context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4221                         return false;
4222                     }
4223                     break;
4224 
4225                 default:
4226                     context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4227                     return false;
4228             }
4229         }
4230     }
4231 
4232     const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
4233     if (attachmentObject)
4234     {
4235         ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4236                attachmentObject->type() == GL_TEXTURE ||
4237                attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4238 
4239         switch (pname)
4240         {
4241             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4242                 if (attachmentObject->type() != GL_RENDERBUFFER &&
4243                     attachmentObject->type() != GL_TEXTURE)
4244                 {
4245                     context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4246                     return false;
4247                 }
4248                 break;
4249 
4250             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4251                 if (attachmentObject->type() != GL_TEXTURE)
4252                 {
4253                     context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4254                     return false;
4255                 }
4256                 break;
4257 
4258             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4259                 if (attachmentObject->type() != GL_TEXTURE)
4260                 {
4261                     context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4262                     return false;
4263                 }
4264                 break;
4265 
4266             case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4267                 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4268                 {
4269                     context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4270                     return false;
4271                 }
4272                 break;
4273 
4274             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4275                 if (attachmentObject->type() != GL_TEXTURE)
4276                 {
4277                     context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4278                     return false;
4279                 }
4280                 break;
4281 
4282             default:
4283                 break;
4284         }
4285     }
4286     else
4287     {
4288         // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4289         // is NONE, then querying any other pname will generate INVALID_ENUM.
4290 
4291         // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4292         // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4293         // INVALID_OPERATION for all other pnames
4294 
4295         switch (pname)
4296         {
4297             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4298                 break;
4299 
4300             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4301                 if (clientVersion < 3)
4302                 {
4303                     context->validationError(GL_INVALID_ENUM,
4304                                              kInvalidFramebufferAttachmentParameter);
4305                     return false;
4306                 }
4307                 break;
4308 
4309             default:
4310                 if (clientVersion < 3)
4311                 {
4312                     context->validationError(GL_INVALID_ENUM,
4313                                              kInvalidFramebufferAttachmentParameter);
4314                     return false;
4315                 }
4316                 else
4317                 {
4318                     context->validationError(GL_INVALID_OPERATION,
4319                                              kInvalidFramebufferAttachmentParameter);
4320                     return false;
4321                 }
4322         }
4323     }
4324 
4325     if (numParams)
4326     {
4327         *numParams = 1;
4328     }
4329 
4330     return true;
4331 }
4332 
ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context * context,GLenum target,GLenum attachment,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4333 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
4334                                                             GLenum target,
4335                                                             GLenum attachment,
4336                                                             GLenum pname,
4337                                                             GLsizei bufSize,
4338                                                             const GLsizei *length,
4339                                                             const GLint *params)
4340 {
4341     if (!ValidateRobustEntryPoint(context, bufSize))
4342     {
4343         return false;
4344     }
4345 
4346     GLsizei numParams = 0;
4347     if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4348                                                          &numParams))
4349     {
4350         return false;
4351     }
4352 
4353     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4354     {
4355         return false;
4356     }
4357 
4358     SetRobustLengthParam(length, numParams);
4359 
4360     return true;
4361 }
4362 
ValidateGetBufferParameterivRobustANGLE(const Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4363 bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
4364                                              BufferBinding target,
4365                                              GLenum pname,
4366                                              GLsizei bufSize,
4367                                              const GLsizei *length,
4368                                              const GLint *params)
4369 {
4370     if (!ValidateRobustEntryPoint(context, bufSize))
4371     {
4372         return false;
4373     }
4374 
4375     GLsizei numParams = 0;
4376 
4377     if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
4378     {
4379         return false;
4380     }
4381 
4382     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4383     {
4384         return false;
4385     }
4386 
4387     SetRobustLengthParam(length, numParams);
4388     return true;
4389 }
4390 
ValidateGetBufferParameteri64vRobustANGLE(const Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint64 * params)4391 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
4392                                                BufferBinding target,
4393                                                GLenum pname,
4394                                                GLsizei bufSize,
4395                                                const GLsizei *length,
4396                                                const GLint64 *params)
4397 {
4398     GLsizei numParams = 0;
4399 
4400     if (!ValidateRobustEntryPoint(context, bufSize))
4401     {
4402         return false;
4403     }
4404 
4405     if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
4406     {
4407         return false;
4408     }
4409 
4410     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4411     {
4412         return false;
4413     }
4414 
4415     SetRobustLengthParam(length, numParams);
4416 
4417     return true;
4418 }
4419 
ValidateGetProgramivBase(const Context * context,ShaderProgramID program,GLenum pname,GLsizei * numParams)4420 bool ValidateGetProgramivBase(const Context *context,
4421                               ShaderProgramID program,
4422                               GLenum pname,
4423                               GLsizei *numParams)
4424 {
4425     // Currently, all GetProgramiv queries return 1 parameter
4426     if (numParams)
4427     {
4428         *numParams = 1;
4429     }
4430 
4431     if (context->isContextLost())
4432     {
4433         context->validationError(GL_CONTEXT_LOST, kContextLost);
4434 
4435         if (context->getExtensions().parallelShaderCompile && pname == GL_COMPLETION_STATUS_KHR)
4436         {
4437             // Generate an error but still return true, the context still needs to return a
4438             // value in this case.
4439             return true;
4440         }
4441         else
4442         {
4443             return false;
4444         }
4445     }
4446 
4447     // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4448     Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4449                                  ? GetValidProgramNoResolve(context, program)
4450                                  : GetValidProgram(context, program);
4451     if (!programObject)
4452     {
4453         return false;
4454     }
4455 
4456     switch (pname)
4457     {
4458         case GL_DELETE_STATUS:
4459         case GL_LINK_STATUS:
4460         case GL_VALIDATE_STATUS:
4461         case GL_INFO_LOG_LENGTH:
4462         case GL_ATTACHED_SHADERS:
4463         case GL_ACTIVE_ATTRIBUTES:
4464         case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4465         case GL_ACTIVE_UNIFORMS:
4466         case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4467             break;
4468 
4469         case GL_PROGRAM_BINARY_LENGTH:
4470             if (context->getClientMajorVersion() < 3 &&
4471                 !context->getExtensions().getProgramBinaryOES)
4472             {
4473                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4474                 return false;
4475             }
4476             break;
4477 
4478         case GL_ACTIVE_UNIFORM_BLOCKS:
4479         case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4480         case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4481         case GL_TRANSFORM_FEEDBACK_VARYINGS:
4482         case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4483         case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4484             if (context->getClientMajorVersion() < 3)
4485             {
4486                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
4487                 return false;
4488             }
4489             break;
4490 
4491         case GL_PROGRAM_SEPARABLE:
4492         case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
4493             if (context->getClientVersion() < Version(3, 1))
4494             {
4495                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
4496                 return false;
4497             }
4498             break;
4499 
4500         case GL_COMPUTE_WORK_GROUP_SIZE:
4501             if (context->getClientVersion() < Version(3, 1))
4502             {
4503                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
4504                 return false;
4505             }
4506 
4507             // [OpenGL ES 3.1] Chapter 7.12 Page 122
4508             // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4509             // program which has not been linked successfully, or which does not contain objects to
4510             // form a compute shader.
4511             if (!programObject->isLinked())
4512             {
4513                 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4514                 return false;
4515             }
4516             if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
4517             {
4518                 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
4519                 return false;
4520             }
4521             break;
4522 
4523         case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4524         case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4525         case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4526         case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4527             if (!context->getExtensions().geometryShader)
4528             {
4529                 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4530                 return false;
4531             }
4532 
4533             // [EXT_geometry_shader] Chapter 7.12
4534             // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4535             // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4536             // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4537             // successfully, or which does not contain objects to form a geometry shader.
4538             if (!programObject->isLinked())
4539             {
4540                 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4541                 return false;
4542             }
4543             if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
4544             {
4545                 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
4546                 return false;
4547             }
4548             break;
4549 
4550         case GL_COMPLETION_STATUS_KHR:
4551             if (!context->getExtensions().parallelShaderCompile)
4552             {
4553                 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4554                 return false;
4555             }
4556             break;
4557 
4558         default:
4559             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4560             return false;
4561     }
4562 
4563     return true;
4564 }
4565 
ValidateGetProgramivRobustANGLE(const Context * context,ShaderProgramID program,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4566 bool ValidateGetProgramivRobustANGLE(const Context *context,
4567                                      ShaderProgramID program,
4568                                      GLenum pname,
4569                                      GLsizei bufSize,
4570                                      const GLsizei *length,
4571                                      const GLint *params)
4572 {
4573     if (!ValidateRobustEntryPoint(context, bufSize))
4574     {
4575         return false;
4576     }
4577 
4578     GLsizei numParams = 0;
4579 
4580     if (!ValidateGetProgramivBase(context, program, pname, &numParams))
4581     {
4582         return false;
4583     }
4584 
4585     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4586     {
4587         return false;
4588     }
4589 
4590     SetRobustLengthParam(length, numParams);
4591 
4592     return true;
4593 }
4594 
ValidateGetRenderbufferParameterivRobustANGLE(const Context * context,GLenum target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4595 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
4596                                                    GLenum target,
4597                                                    GLenum pname,
4598                                                    GLsizei bufSize,
4599                                                    const GLsizei *length,
4600                                                    const GLint *params)
4601 {
4602     if (!ValidateRobustEntryPoint(context, bufSize))
4603     {
4604         return false;
4605     }
4606 
4607     GLsizei numParams = 0;
4608 
4609     if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
4610     {
4611         return false;
4612     }
4613 
4614     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4615     {
4616         return false;
4617     }
4618 
4619     SetRobustLengthParam(length, numParams);
4620 
4621     return true;
4622 }
4623 
ValidateGetShaderivRobustANGLE(const Context * context,ShaderProgramID shader,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4624 bool ValidateGetShaderivRobustANGLE(const Context *context,
4625                                     ShaderProgramID shader,
4626                                     GLenum pname,
4627                                     GLsizei bufSize,
4628                                     const GLsizei *length,
4629                                     const GLint *params)
4630 {
4631     if (!ValidateRobustEntryPoint(context, bufSize))
4632     {
4633         return false;
4634     }
4635 
4636     GLsizei numParams = 0;
4637 
4638     if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
4639     {
4640         return false;
4641     }
4642 
4643     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4644     {
4645         return false;
4646     }
4647 
4648     SetRobustLengthParam(length, numParams);
4649 
4650     return true;
4651 }
4652 
ValidateGetTexParameterfvRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4653 bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
4654                                           TextureType target,
4655                                           GLenum pname,
4656                                           GLsizei bufSize,
4657                                           const GLsizei *length,
4658                                           const GLfloat *params)
4659 {
4660     if (!ValidateRobustEntryPoint(context, bufSize))
4661     {
4662         return false;
4663     }
4664 
4665     GLsizei numParams = 0;
4666 
4667     if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
4668     {
4669         return false;
4670     }
4671 
4672     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4673     {
4674         return false;
4675     }
4676 
4677     SetRobustLengthParam(length, numParams);
4678 
4679     return true;
4680 }
4681 
ValidateGetTexParameterivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4682 bool ValidateGetTexParameterivRobustANGLE(const Context *context,
4683                                           TextureType target,
4684                                           GLenum pname,
4685                                           GLsizei bufSize,
4686                                           const GLsizei *length,
4687                                           const GLint *params)
4688 {
4689 
4690     if (!ValidateRobustEntryPoint(context, bufSize))
4691     {
4692         return false;
4693     }
4694     GLsizei numParams = 0;
4695     if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
4696     {
4697         return false;
4698     }
4699 
4700     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4701     {
4702         return false;
4703     }
4704 
4705     SetRobustLengthParam(length, numParams);
4706     return true;
4707 }
4708 
ValidateGetTexParameterIivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4709 bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
4710                                            TextureType target,
4711                                            GLenum pname,
4712                                            GLsizei bufSize,
4713                                            const GLsizei *length,
4714                                            const GLint *params)
4715 {
4716     UNIMPLEMENTED();
4717     return false;
4718 }
4719 
ValidateGetTexParameterIuivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)4720 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
4721                                             TextureType target,
4722                                             GLenum pname,
4723                                             GLsizei bufSize,
4724                                             const GLsizei *length,
4725                                             const GLuint *params)
4726 {
4727     UNIMPLEMENTED();
4728     return false;
4729 }
4730 
ValidateTexParameterfvRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLfloat * params)4731 bool ValidateTexParameterfvRobustANGLE(const Context *context,
4732                                        TextureType target,
4733                                        GLenum pname,
4734                                        GLsizei bufSize,
4735                                        const GLfloat *params)
4736 {
4737     if (!ValidateRobustEntryPoint(context, bufSize))
4738     {
4739         return false;
4740     }
4741 
4742     return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
4743 }
4744 
ValidateTexParameterivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)4745 bool ValidateTexParameterivRobustANGLE(const Context *context,
4746                                        TextureType target,
4747                                        GLenum pname,
4748                                        GLsizei bufSize,
4749                                        const GLint *params)
4750 {
4751     if (!ValidateRobustEntryPoint(context, bufSize))
4752     {
4753         return false;
4754     }
4755 
4756     return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
4757 }
4758 
ValidateTexParameterIivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)4759 bool ValidateTexParameterIivRobustANGLE(const Context *context,
4760                                         TextureType target,
4761                                         GLenum pname,
4762                                         GLsizei bufSize,
4763                                         const GLint *params)
4764 {
4765     UNIMPLEMENTED();
4766     return false;
4767 }
4768 
ValidateTexParameterIuivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLuint * params)4769 bool ValidateTexParameterIuivRobustANGLE(const Context *context,
4770                                          TextureType target,
4771                                          GLenum pname,
4772                                          GLsizei bufSize,
4773                                          const GLuint *params)
4774 {
4775     UNIMPLEMENTED();
4776     return false;
4777 }
4778 
ValidateGetSamplerParameterfvRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4779 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
4780                                               SamplerID sampler,
4781                                               GLenum pname,
4782                                               GLsizei bufSize,
4783                                               const GLsizei *length,
4784                                               const GLfloat *params)
4785 {
4786     if (!ValidateRobustEntryPoint(context, bufSize))
4787     {
4788         return false;
4789     }
4790 
4791     GLsizei numParams = 0;
4792 
4793     if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
4794     {
4795         return false;
4796     }
4797 
4798     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4799     {
4800         return false;
4801     }
4802 
4803     SetRobustLengthParam(length, numParams);
4804     return true;
4805 }
4806 
ValidateGetSamplerParameterivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4807 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
4808                                               SamplerID sampler,
4809                                               GLenum pname,
4810                                               GLsizei bufSize,
4811                                               const GLsizei *length,
4812                                               const GLint *params)
4813 {
4814     if (!ValidateRobustEntryPoint(context, bufSize))
4815     {
4816         return false;
4817     }
4818 
4819     GLsizei numParams = 0;
4820 
4821     if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
4822     {
4823         return false;
4824     }
4825 
4826     if (!ValidateRobustBufferSize(context, bufSize, numParams))
4827     {
4828         return false;
4829     }
4830 
4831     SetRobustLengthParam(length, numParams);
4832     return true;
4833 }
4834 
ValidateGetSamplerParameterIivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4835 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
4836                                                SamplerID sampler,
4837                                                GLenum pname,
4838                                                GLsizei bufSize,
4839                                                const GLsizei *length,
4840                                                const GLint *params)
4841 {
4842     UNIMPLEMENTED();
4843     return false;
4844 }
4845 
ValidateGetSamplerParameterIuivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)4846 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
4847                                                 SamplerID sampler,
4848                                                 GLenum pname,
4849                                                 GLsizei bufSize,
4850                                                 const GLsizei *length,
4851                                                 const GLuint *params)
4852 {
4853     UNIMPLEMENTED();
4854     return false;
4855 }
4856 
ValidateSamplerParameterfvRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLfloat * params)4857 bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
4858                                            SamplerID sampler,
4859                                            GLenum pname,
4860                                            GLsizei bufSize,
4861                                            const GLfloat *params)
4862 {
4863     if (!ValidateRobustEntryPoint(context, bufSize))
4864     {
4865         return false;
4866     }
4867 
4868     return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
4869 }
4870 
ValidateSamplerParameterivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * params)4871 bool ValidateSamplerParameterivRobustANGLE(const Context *context,
4872                                            SamplerID sampler,
4873                                            GLenum pname,
4874                                            GLsizei bufSize,
4875                                            const GLint *params)
4876 {
4877     if (!ValidateRobustEntryPoint(context, bufSize))
4878     {
4879         return false;
4880     }
4881 
4882     return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
4883 }
4884 
ValidateSamplerParameterIivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * param)4885 bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
4886                                             SamplerID sampler,
4887                                             GLenum pname,
4888                                             GLsizei bufSize,
4889                                             const GLint *param)
4890 {
4891     UNIMPLEMENTED();
4892     return false;
4893 }
4894 
ValidateSamplerParameterIuivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLuint * param)4895 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
4896                                              SamplerID sampler,
4897                                              GLenum pname,
4898                                              GLsizei bufSize,
4899                                              const GLuint *param)
4900 {
4901     UNIMPLEMENTED();
4902     return false;
4903 }
4904 
ValidateGetVertexAttribfvRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4905 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
4906                                           GLuint index,
4907                                           GLenum pname,
4908                                           GLsizei bufSize,
4909                                           const GLsizei *length,
4910                                           const GLfloat *params)
4911 {
4912     if (!ValidateRobustEntryPoint(context, bufSize))
4913     {
4914         return false;
4915     }
4916 
4917     GLsizei writeLength = 0;
4918 
4919     if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
4920     {
4921         return false;
4922     }
4923 
4924     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
4925     {
4926         return false;
4927     }
4928 
4929     SetRobustLengthParam(length, writeLength);
4930     return true;
4931 }
4932 
ValidateGetVertexAttribivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4933 bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
4934                                           GLuint index,
4935                                           GLenum pname,
4936                                           GLsizei bufSize,
4937                                           const GLsizei *length,
4938                                           const GLint *params)
4939 {
4940     if (!ValidateRobustEntryPoint(context, bufSize))
4941     {
4942         return false;
4943     }
4944 
4945     GLsizei writeLength = 0;
4946 
4947     if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
4948     {
4949         return false;
4950     }
4951 
4952     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
4953     {
4954         return false;
4955     }
4956 
4957     SetRobustLengthParam(length, writeLength);
4958 
4959     return true;
4960 }
4961 
ValidateGetVertexAttribPointervRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * pointer)4962 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
4963                                                 GLuint index,
4964                                                 GLenum pname,
4965                                                 GLsizei bufSize,
4966                                                 const GLsizei *length,
4967                                                 void *const *pointer)
4968 {
4969     if (!ValidateRobustEntryPoint(context, bufSize))
4970     {
4971         return false;
4972     }
4973 
4974     GLsizei writeLength = 0;
4975 
4976     if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
4977     {
4978         return false;
4979     }
4980 
4981     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
4982     {
4983         return false;
4984     }
4985 
4986     SetRobustLengthParam(length, writeLength);
4987 
4988     return true;
4989 }
4990 
ValidateGetVertexAttribIivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4991 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
4992                                            GLuint index,
4993                                            GLenum pname,
4994                                            GLsizei bufSize,
4995                                            const GLsizei *length,
4996                                            const GLint *params)
4997 {
4998     if (!ValidateRobustEntryPoint(context, bufSize))
4999     {
5000         return false;
5001     }
5002 
5003     GLsizei writeLength = 0;
5004 
5005     if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
5006     {
5007         return false;
5008     }
5009 
5010     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5011     {
5012         return false;
5013     }
5014 
5015     SetRobustLengthParam(length, writeLength);
5016 
5017     return true;
5018 }
5019 
ValidateGetVertexAttribIuivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)5020 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
5021                                             GLuint index,
5022                                             GLenum pname,
5023                                             GLsizei bufSize,
5024                                             const GLsizei *length,
5025                                             const GLuint *params)
5026 {
5027     if (!ValidateRobustEntryPoint(context, bufSize))
5028     {
5029         return false;
5030     }
5031 
5032     GLsizei writeLength = 0;
5033 
5034     if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
5035     {
5036         return false;
5037     }
5038 
5039     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5040     {
5041         return false;
5042     }
5043 
5044     SetRobustLengthParam(length, writeLength);
5045 
5046     return true;
5047 }
5048 
ValidateGetActiveUniformBlockivRobustANGLE(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5049 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
5050                                                 ShaderProgramID program,
5051                                                 GLuint uniformBlockIndex,
5052                                                 GLenum pname,
5053                                                 GLsizei bufSize,
5054                                                 const GLsizei *length,
5055                                                 const GLint *params)
5056 {
5057     if (!ValidateRobustEntryPoint(context, bufSize))
5058     {
5059         return false;
5060     }
5061 
5062     GLsizei writeLength = 0;
5063 
5064     if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5065                                              &writeLength))
5066     {
5067         return false;
5068     }
5069 
5070     if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5071     {
5072         return false;
5073     }
5074 
5075     SetRobustLengthParam(length, writeLength);
5076 
5077     return true;
5078 }
5079 
ValidateGetInternalformativRobustANGLE(const Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5080 bool ValidateGetInternalformativRobustANGLE(const Context *context,
5081                                             GLenum target,
5082                                             GLenum internalformat,
5083                                             GLenum pname,
5084                                             GLsizei bufSize,
5085                                             const GLsizei *length,
5086                                             const GLint *params)
5087 {
5088     if (!ValidateRobustEntryPoint(context, bufSize))
5089     {
5090         return false;
5091     }
5092 
5093     GLsizei numParams = 0;
5094 
5095     if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5096                                          &numParams))
5097     {
5098         return false;
5099     }
5100 
5101     if (!ValidateRobustBufferSize(context, bufSize, numParams))
5102     {
5103         return false;
5104     }
5105 
5106     SetRobustLengthParam(length, numParams);
5107 
5108     return true;
5109 }
5110 
5111 // Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5112 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5113 // specified clear value and the type of a buffer that is being cleared generates an
5114 // INVALID_OPERATION error instead of producing undefined results
ValidateWebGLFramebufferAttachmentClearType(const Context * context,GLint drawbuffer,const GLenum * validComponentTypes,size_t validComponentTypeCount)5115 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
5116                                                  GLint drawbuffer,
5117                                                  const GLenum *validComponentTypes,
5118                                                  size_t validComponentTypeCount)
5119 {
5120     const FramebufferAttachment *attachment =
5121         context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5122     if (attachment)
5123     {
5124         GLenum componentType = attachment->getFormat().info->componentType;
5125         const GLenum *end    = validComponentTypes + validComponentTypeCount;
5126         if (std::find(validComponentTypes, end, componentType) == end)
5127         {
5128             context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
5129             return false;
5130         }
5131     }
5132 
5133     return true;
5134 }
5135 
ValidateRobustCompressedTexImageBase(const Context * context,GLsizei imageSize,GLsizei dataSize)5136 bool ValidateRobustCompressedTexImageBase(const Context *context,
5137                                           GLsizei imageSize,
5138                                           GLsizei dataSize)
5139 {
5140     if (!ValidateRobustEntryPoint(context, dataSize))
5141     {
5142         return false;
5143     }
5144 
5145     Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
5146     if (pixelUnpackBuffer == nullptr)
5147     {
5148         if (dataSize < imageSize)
5149         {
5150             context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
5151         }
5152     }
5153     return true;
5154 }
5155 
ValidateGetBufferParameterBase(const Context * context,BufferBinding target,GLenum pname,bool pointerVersion,GLsizei * numParams)5156 bool ValidateGetBufferParameterBase(const Context *context,
5157                                     BufferBinding target,
5158                                     GLenum pname,
5159                                     bool pointerVersion,
5160                                     GLsizei *numParams)
5161 {
5162     if (numParams)
5163     {
5164         *numParams = 0;
5165     }
5166 
5167     if (!context->isValidBufferBinding(target))
5168     {
5169         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
5170         return false;
5171     }
5172 
5173     const Buffer *buffer = context->getState().getTargetBuffer(target);
5174     if (!buffer)
5175     {
5176         // A null buffer means that "0" is bound to the requested buffer target
5177         context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
5178         return false;
5179     }
5180 
5181     const Extensions &extensions = context->getExtensions();
5182 
5183     switch (pname)
5184     {
5185         case GL_BUFFER_USAGE:
5186         case GL_BUFFER_SIZE:
5187             break;
5188 
5189         case GL_BUFFER_ACCESS_OES:
5190             if (!extensions.mapBufferOES)
5191             {
5192                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5193                 return false;
5194             }
5195             break;
5196 
5197         case GL_BUFFER_MAPPED:
5198             static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5199             if (context->getClientMajorVersion() < 3 && !extensions.mapBufferOES &&
5200                 !extensions.mapBufferRange)
5201             {
5202                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5203                 return false;
5204             }
5205             break;
5206 
5207         case GL_BUFFER_MAP_POINTER:
5208             if (!pointerVersion)
5209             {
5210                 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
5211                 return false;
5212             }
5213             break;
5214 
5215         case GL_BUFFER_ACCESS_FLAGS:
5216         case GL_BUFFER_MAP_OFFSET:
5217         case GL_BUFFER_MAP_LENGTH:
5218             if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5219             {
5220                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5221                 return false;
5222             }
5223             break;
5224 
5225         case GL_MEMORY_SIZE_ANGLE:
5226             if (!context->getExtensions().memorySize)
5227             {
5228                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5229                 return false;
5230             }
5231             break;
5232 
5233         default:
5234             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5235             return false;
5236     }
5237 
5238     // All buffer parameter queries return one value.
5239     if (numParams)
5240     {
5241         *numParams = 1;
5242     }
5243 
5244     return true;
5245 }
5246 
ValidateGetRenderbufferParameterivBase(const Context * context,GLenum target,GLenum pname,GLsizei * length)5247 bool ValidateGetRenderbufferParameterivBase(const Context *context,
5248                                             GLenum target,
5249                                             GLenum pname,
5250                                             GLsizei *length)
5251 {
5252     if (length)
5253     {
5254         *length = 0;
5255     }
5256 
5257     if (target != GL_RENDERBUFFER)
5258     {
5259         context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
5260         return false;
5261     }
5262 
5263     Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
5264     if (renderbuffer == nullptr)
5265     {
5266         context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
5267         return false;
5268     }
5269 
5270     switch (pname)
5271     {
5272         case GL_RENDERBUFFER_WIDTH:
5273         case GL_RENDERBUFFER_HEIGHT:
5274         case GL_RENDERBUFFER_INTERNAL_FORMAT:
5275         case GL_RENDERBUFFER_RED_SIZE:
5276         case GL_RENDERBUFFER_GREEN_SIZE:
5277         case GL_RENDERBUFFER_BLUE_SIZE:
5278         case GL_RENDERBUFFER_ALPHA_SIZE:
5279         case GL_RENDERBUFFER_DEPTH_SIZE:
5280         case GL_RENDERBUFFER_STENCIL_SIZE:
5281             break;
5282 
5283         case GL_RENDERBUFFER_SAMPLES_ANGLE:
5284             if (!context->getExtensions().framebufferMultisample)
5285             {
5286                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5287                 return false;
5288             }
5289             break;
5290 
5291         case GL_MEMORY_SIZE_ANGLE:
5292             if (!context->getExtensions().memorySize)
5293             {
5294                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5295                 return false;
5296             }
5297             break;
5298 
5299         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5300         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5301             if (!context->getExtensions().getImageANGLE)
5302             {
5303                 context->validationError(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
5304                 return false;
5305             }
5306             break;
5307 
5308         default:
5309             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5310             return false;
5311     }
5312 
5313     if (length)
5314     {
5315         *length = 1;
5316     }
5317     return true;
5318 }
5319 
ValidateGetShaderivBase(const Context * context,ShaderProgramID shader,GLenum pname,GLsizei * length)5320 bool ValidateGetShaderivBase(const Context *context,
5321                              ShaderProgramID shader,
5322                              GLenum pname,
5323                              GLsizei *length)
5324 {
5325     if (length)
5326     {
5327         *length = 0;
5328     }
5329 
5330     if (context->isContextLost())
5331     {
5332         context->validationError(GL_CONTEXT_LOST, kContextLost);
5333 
5334         if (context->getExtensions().parallelShaderCompile && pname == GL_COMPLETION_STATUS_KHR)
5335         {
5336             // Generate an error but still return true, the context still needs to return a
5337             // value in this case.
5338             return true;
5339         }
5340         else
5341         {
5342             return false;
5343         }
5344     }
5345 
5346     if (GetValidShader(context, shader) == nullptr)
5347     {
5348         return false;
5349     }
5350 
5351     switch (pname)
5352     {
5353         case GL_SHADER_TYPE:
5354         case GL_DELETE_STATUS:
5355         case GL_COMPILE_STATUS:
5356         case GL_INFO_LOG_LENGTH:
5357         case GL_SHADER_SOURCE_LENGTH:
5358             break;
5359 
5360         case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5361             if (!context->getExtensions().translatedShaderSource)
5362             {
5363                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5364                 return false;
5365             }
5366             break;
5367 
5368         case GL_COMPLETION_STATUS_KHR:
5369             if (!context->getExtensions().parallelShaderCompile)
5370             {
5371                 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5372                 return false;
5373             }
5374             break;
5375 
5376         default:
5377             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5378             return false;
5379     }
5380 
5381     if (length)
5382     {
5383         *length = 1;
5384     }
5385     return true;
5386 }
5387 
ValidateGetTexParameterBase(const Context * context,TextureType target,GLenum pname,GLsizei * length)5388 bool ValidateGetTexParameterBase(const Context *context,
5389                                  TextureType target,
5390                                  GLenum pname,
5391                                  GLsizei *length)
5392 {
5393     if (length)
5394     {
5395         *length = 0;
5396     }
5397 
5398     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5399     {
5400         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5401         return false;
5402     }
5403 
5404     if (context->getTextureByType(target) == nullptr)
5405     {
5406         // Should only be possible for external textures
5407         context->validationError(GL_INVALID_ENUM, kTextureNotBound);
5408         return false;
5409     }
5410 
5411     if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5412     {
5413         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5414         return false;
5415     }
5416 
5417     switch (pname)
5418     {
5419         case GL_TEXTURE_MAG_FILTER:
5420         case GL_TEXTURE_MIN_FILTER:
5421         case GL_TEXTURE_WRAP_S:
5422         case GL_TEXTURE_WRAP_T:
5423             break;
5424 
5425         case GL_TEXTURE_USAGE_ANGLE:
5426             if (!context->getExtensions().textureUsage)
5427             {
5428                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5429                 return false;
5430             }
5431             break;
5432 
5433         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5434             if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5435             {
5436                 return false;
5437             }
5438             break;
5439 
5440         case GL_TEXTURE_IMMUTABLE_FORMAT:
5441             if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5442             {
5443                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5444                 return false;
5445             }
5446             break;
5447 
5448         case GL_TEXTURE_WRAP_R:
5449         case GL_TEXTURE_IMMUTABLE_LEVELS:
5450         case GL_TEXTURE_SWIZZLE_R:
5451         case GL_TEXTURE_SWIZZLE_G:
5452         case GL_TEXTURE_SWIZZLE_B:
5453         case GL_TEXTURE_SWIZZLE_A:
5454         case GL_TEXTURE_BASE_LEVEL:
5455         case GL_TEXTURE_MAX_LEVEL:
5456         case GL_TEXTURE_MIN_LOD:
5457         case GL_TEXTURE_MAX_LOD:
5458         case GL_TEXTURE_COMPARE_MODE:
5459         case GL_TEXTURE_COMPARE_FUNC:
5460             if (context->getClientMajorVersion() < 3)
5461             {
5462                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
5463                 return false;
5464             }
5465             break;
5466 
5467         case GL_TEXTURE_SRGB_DECODE_EXT:
5468             if (!context->getExtensions().textureSRGBDecode)
5469             {
5470                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5471                 return false;
5472             }
5473             break;
5474 
5475         case GL_DEPTH_STENCIL_TEXTURE_MODE:
5476         case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
5477             if (context->getClientVersion() < Version(3, 1))
5478             {
5479                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
5480                 return false;
5481             }
5482             break;
5483 
5484         case GL_GENERATE_MIPMAP:
5485         case GL_TEXTURE_CROP_RECT_OES:
5486             // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5487             // after GL_OES_draw_texture functionality implemented
5488             if (context->getClientMajorVersion() > 1)
5489             {
5490                 context->validationError(GL_INVALID_ENUM, kGLES1Only);
5491                 return false;
5492             }
5493             break;
5494 
5495         case GL_MEMORY_SIZE_ANGLE:
5496             if (!context->getExtensions().memorySize)
5497             {
5498                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5499                 return false;
5500             }
5501             break;
5502 
5503         case GL_TEXTURE_BORDER_COLOR:
5504             if (!context->getExtensions().textureBorderClampOES)
5505             {
5506                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5507                 return false;
5508             }
5509             break;
5510 
5511         case GL_TEXTURE_NATIVE_ID_ANGLE:
5512             if (!context->getExtensions().textureExternalUpdateANGLE)
5513             {
5514                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5515                 return false;
5516             }
5517             break;
5518 
5519         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5520         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5521             if (!context->getExtensions().getImageANGLE)
5522             {
5523                 context->validationError(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
5524                 return false;
5525             }
5526             break;
5527 
5528         default:
5529             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5530             return false;
5531     }
5532 
5533     if (length)
5534     {
5535         *length = GetTexParameterCount(pname);
5536     }
5537     return true;
5538 }
5539 
ValidateGetVertexAttribBase(const Context * context,GLuint index,GLenum pname,GLsizei * length,bool pointer,bool pureIntegerEntryPoint)5540 bool ValidateGetVertexAttribBase(const Context *context,
5541                                  GLuint index,
5542                                  GLenum pname,
5543                                  GLsizei *length,
5544                                  bool pointer,
5545                                  bool pureIntegerEntryPoint)
5546 {
5547     if (length)
5548     {
5549         *length = 0;
5550     }
5551 
5552     if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5553     {
5554         context->validationError(GL_INVALID_OPERATION, kES3Required);
5555         return false;
5556     }
5557 
5558     if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
5559     {
5560         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
5561         return false;
5562     }
5563 
5564     if (pointer)
5565     {
5566         if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5567         {
5568             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5569             return false;
5570         }
5571     }
5572     else
5573     {
5574         switch (pname)
5575         {
5576             case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5577             case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5578             case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5579             case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5580             case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5581             case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5582             case GL_CURRENT_VERTEX_ATTRIB:
5583                 break;
5584 
5585             case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5586                 static_assert(
5587                     GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5588                     "ANGLE extension enums not equal to GL enums.");
5589                 if (context->getClientMajorVersion() < 3 &&
5590                     !context->getExtensions().instancedArraysAny())
5591                 {
5592                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5593                     return false;
5594                 }
5595                 break;
5596 
5597             case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5598                 if (context->getClientMajorVersion() < 3)
5599                 {
5600                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5601                     return false;
5602                 }
5603                 break;
5604 
5605             case GL_VERTEX_ATTRIB_BINDING:
5606             case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5607                 if (context->getClientVersion() < ES_3_1)
5608                 {
5609                     context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
5610                     return false;
5611                 }
5612                 break;
5613 
5614             default:
5615                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5616                 return false;
5617         }
5618     }
5619 
5620     if (length)
5621     {
5622         if (pname == GL_CURRENT_VERTEX_ATTRIB)
5623         {
5624             *length = 4;
5625         }
5626         else
5627         {
5628             *length = 1;
5629         }
5630     }
5631 
5632     return true;
5633 }
5634 
ValidatePixelPack(const Context * context,GLenum format,GLenum type,GLint x,GLint y,GLsizei width,GLsizei height,GLsizei bufSize,GLsizei * length,const void * pixels)5635 bool ValidatePixelPack(const Context *context,
5636                        GLenum format,
5637                        GLenum type,
5638                        GLint x,
5639                        GLint y,
5640                        GLsizei width,
5641                        GLsizei height,
5642                        GLsizei bufSize,
5643                        GLsizei *length,
5644                        const void *pixels)
5645 {
5646     // Check for pixel pack buffer related API errors
5647     Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
5648     if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5649     {
5650         // ...the buffer object's data store is currently mapped.
5651         context->validationError(GL_INVALID_OPERATION, kBufferMapped);
5652         return false;
5653     }
5654     if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5655         pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5656     {
5657         context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
5658         return false;
5659     }
5660 
5661     // ..  the data would be packed to the buffer object such that the memory writes required
5662     // would exceed the data store size.
5663     const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5664     const Extents size(width, height, 1);
5665     const auto &pack = context->getState().getPackState();
5666 
5667     GLuint endByte = 0;
5668     if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
5669     {
5670         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5671         return false;
5672     }
5673 
5674     if (bufSize >= 0)
5675     {
5676         if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5677         {
5678             context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
5679             return false;
5680         }
5681     }
5682 
5683     if (pixelPackBuffer != nullptr)
5684     {
5685         CheckedNumeric<size_t> checkedEndByte(endByte);
5686         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5687         checkedEndByte += checkedOffset;
5688 
5689         if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5690         {
5691             // Overflow past the end of the buffer
5692             context->validationError(GL_INVALID_OPERATION, kParamOverflow);
5693             return false;
5694         }
5695     }
5696 
5697     if (pixelPackBuffer == nullptr && length != nullptr)
5698     {
5699         if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5700         {
5701             context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5702             return false;
5703         }
5704 
5705         *length = static_cast<GLsizei>(endByte);
5706     }
5707 
5708     return true;
5709 }
5710 
ValidateReadPixelsBase(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,const void * pixels)5711 bool ValidateReadPixelsBase(const Context *context,
5712                             GLint x,
5713                             GLint y,
5714                             GLsizei width,
5715                             GLsizei height,
5716                             GLenum format,
5717                             GLenum type,
5718                             GLsizei bufSize,
5719                             GLsizei *length,
5720                             GLsizei *columns,
5721                             GLsizei *rows,
5722                             const void *pixels)
5723 {
5724     if (length != nullptr)
5725     {
5726         *length = 0;
5727     }
5728     if (rows != nullptr)
5729     {
5730         *rows = 0;
5731     }
5732     if (columns != nullptr)
5733     {
5734         *columns = 0;
5735     }
5736 
5737     if (width < 0 || height < 0)
5738     {
5739         context->validationError(GL_INVALID_VALUE, kNegativeSize);
5740         return false;
5741     }
5742 
5743     Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
5744     ASSERT(readFramebuffer);
5745 
5746     if (!ValidateFramebufferComplete(context, readFramebuffer))
5747     {
5748         return false;
5749     }
5750 
5751     // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
5752     // resolved before reading.
5753     if (!readFramebuffer->isDefault() &&
5754         !ValidateFramebufferNotMultisampled(context, readFramebuffer, true))
5755     {
5756         return false;
5757     }
5758 
5759     if (readFramebuffer->getReadBufferState() == GL_NONE)
5760     {
5761         context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
5762         return false;
5763     }
5764 
5765     const FramebufferAttachment *readBuffer = nullptr;
5766     switch (format)
5767     {
5768         case GL_DEPTH_COMPONENT:
5769             readBuffer = readFramebuffer->getDepthAttachment();
5770             break;
5771         case GL_STENCIL_INDEX_OES:
5772             readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
5773             break;
5774         default:
5775             readBuffer = readFramebuffer->getReadColorAttachment();
5776             break;
5777     }
5778 
5779     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5780     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5781     // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5782     // situation is an application error that would lead to a crash in ANGLE.
5783     if (readBuffer == nullptr)
5784     {
5785         context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
5786         return false;
5787     }
5788 
5789     // OVR_multiview2, Revision 1:
5790     // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
5791     // the number of views in the current read framebuffer is more than one.
5792     if (readFramebuffer->readDisallowedByMultiview())
5793     {
5794         context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
5795         return false;
5796     }
5797 
5798     if (context->getExtensions().webglCompatibility)
5799     {
5800         // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5801         // excluding formats LUMINANCE and LUMINANCE_ALPHA.".  This requires validating the format
5802         // and type before validating the combination of format and type.  However, the
5803         // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5804         // verifies that GL_INVALID_OPERATION is generated.
5805         // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5806         // dEQP/WebGL.
5807         if (!ValidReadPixelsFormatEnum(context, format))
5808         {
5809             context->validationError(GL_INVALID_ENUM, kInvalidFormat);
5810             return false;
5811         }
5812 
5813         if (!ValidReadPixelsTypeEnum(context, type))
5814         {
5815             context->validationError(GL_INVALID_ENUM, kInvalidType);
5816             return false;
5817         }
5818     }
5819 
5820     GLenum currentFormat = GL_NONE;
5821     GLenum currentType   = GL_NONE;
5822 
5823     switch (format)
5824     {
5825         case GL_DEPTH_COMPONENT:
5826         case GL_STENCIL_INDEX_OES:
5827             // Only rely on ValidReadPixelsFormatType for depth/stencil formats
5828             break;
5829         default:
5830             currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
5831             currentType   = readFramebuffer->getImplementationColorReadType(context);
5832             break;
5833     }
5834 
5835     bool validFormatTypeCombination =
5836         ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
5837 
5838     if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5839     {
5840         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
5841         return false;
5842     }
5843 
5844     if (!ValidatePixelPack(context, format, type, x, y, width, height, bufSize, length, pixels))
5845     {
5846         return false;
5847     }
5848 
5849     auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
5850         angle::CheckedNumeric<int> clippedExtent(length);
5851         if (start < 0)
5852         {
5853             // "subtract" the area that is less than 0
5854             clippedExtent += start;
5855         }
5856 
5857         angle::CheckedNumeric<int> readExtent = start;
5858         readExtent += length;
5859         if (!readExtent.IsValid())
5860         {
5861             return false;
5862         }
5863 
5864         if (readExtent.ValueOrDie() > bufferSize)
5865         {
5866             // Subtract the region to the right of the read buffer
5867             clippedExtent -= (readExtent - bufferSize);
5868         }
5869 
5870         if (!clippedExtent.IsValid())
5871         {
5872             return false;
5873         }
5874 
5875         *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5876         return true;
5877     };
5878 
5879     GLsizei writtenColumns = 0;
5880     if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5881     {
5882         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5883         return false;
5884     }
5885 
5886     GLsizei writtenRows = 0;
5887     if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5888     {
5889         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5890         return false;
5891     }
5892 
5893     if (columns != nullptr)
5894     {
5895         *columns = writtenColumns;
5896     }
5897 
5898     if (rows != nullptr)
5899     {
5900         *rows = writtenRows;
5901     }
5902 
5903     return true;
5904 }
5905 
5906 template <typename ParamType>
ValidateTexParameterBase(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)5907 bool ValidateTexParameterBase(const Context *context,
5908                               TextureType target,
5909                               GLenum pname,
5910                               GLsizei bufSize,
5911                               bool vectorParams,
5912                               const ParamType *params)
5913 {
5914     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5915     {
5916         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5917         return false;
5918     }
5919 
5920     if (context->getTextureByType(target) == nullptr)
5921     {
5922         // Should only be possible for external textures
5923         context->validationError(GL_INVALID_ENUM, kTextureNotBound);
5924         return false;
5925     }
5926 
5927     const GLsizei minBufSize = GetTexParameterCount(pname);
5928     if (bufSize >= 0 && bufSize < minBufSize)
5929     {
5930         context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
5931         return false;
5932     }
5933 
5934     if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5935     {
5936         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5937         return false;
5938     }
5939 
5940     switch (pname)
5941     {
5942         case GL_TEXTURE_WRAP_R:
5943         case GL_TEXTURE_SWIZZLE_R:
5944         case GL_TEXTURE_SWIZZLE_G:
5945         case GL_TEXTURE_SWIZZLE_B:
5946         case GL_TEXTURE_SWIZZLE_A:
5947         case GL_TEXTURE_BASE_LEVEL:
5948         case GL_TEXTURE_MAX_LEVEL:
5949         case GL_TEXTURE_COMPARE_MODE:
5950         case GL_TEXTURE_COMPARE_FUNC:
5951         case GL_TEXTURE_MIN_LOD:
5952         case GL_TEXTURE_MAX_LOD:
5953             if (context->getClientMajorVersion() < 3 &&
5954                 !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
5955             {
5956                 context->validationError(GL_INVALID_ENUM, kES3Required);
5957                 return false;
5958             }
5959             if (target == TextureType::External &&
5960                 !context->getExtensions().eglImageExternalEssl3OES)
5961             {
5962                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5963                 return false;
5964             }
5965             if (target == TextureType::VideoImage && !context->getExtensions().webglVideoTexture)
5966             {
5967                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5968             }
5969             break;
5970 
5971         case GL_GENERATE_MIPMAP:
5972         case GL_TEXTURE_CROP_RECT_OES:
5973             if (context->getClientMajorVersion() > 1)
5974             {
5975                 context->validationError(GL_INVALID_ENUM, kGLES1Only);
5976                 return false;
5977             }
5978             break;
5979 
5980         default:
5981             break;
5982     }
5983 
5984     if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
5985     {
5986         switch (pname)
5987         {
5988             case GL_TEXTURE_MIN_FILTER:
5989             case GL_TEXTURE_MAG_FILTER:
5990             case GL_TEXTURE_WRAP_S:
5991             case GL_TEXTURE_WRAP_T:
5992             case GL_TEXTURE_WRAP_R:
5993             case GL_TEXTURE_MIN_LOD:
5994             case GL_TEXTURE_MAX_LOD:
5995             case GL_TEXTURE_COMPARE_MODE:
5996             case GL_TEXTURE_COMPARE_FUNC:
5997             case GL_TEXTURE_BORDER_COLOR:
5998                 context->validationError(GL_INVALID_ENUM, kInvalidPname);
5999                 return false;
6000         }
6001     }
6002 
6003     switch (pname)
6004     {
6005         case GL_TEXTURE_WRAP_S:
6006         case GL_TEXTURE_WRAP_T:
6007         case GL_TEXTURE_WRAP_R:
6008         {
6009             bool restrictedWrapModes = ((target == TextureType::External &&
6010                                          !context->getExtensions().eglImageExternalWrapModesEXT) ||
6011                                         target == TextureType::Rectangle);
6012             if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
6013             {
6014                 return false;
6015             }
6016         }
6017         break;
6018 
6019         case GL_TEXTURE_MIN_FILTER:
6020         {
6021             bool restrictedMinFilter =
6022                 target == TextureType::External || target == TextureType::Rectangle;
6023             if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
6024             {
6025                 return false;
6026             }
6027         }
6028         break;
6029 
6030         case GL_TEXTURE_MAG_FILTER:
6031             if (!ValidateTextureMagFilterValue(context, params))
6032             {
6033                 return false;
6034             }
6035             break;
6036 
6037         case GL_TEXTURE_USAGE_ANGLE:
6038             if (!context->getExtensions().textureUsage)
6039             {
6040                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6041                 return false;
6042             }
6043 
6044             switch (ConvertToGLenum(params[0]))
6045             {
6046                 case GL_NONE:
6047                 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6048                     break;
6049 
6050                 default:
6051                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6052                     return false;
6053             }
6054             break;
6055 
6056         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6057         {
6058             GLfloat paramValue = static_cast<GLfloat>(params[0]);
6059             if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6060             {
6061                 return false;
6062             }
6063             ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6064         }
6065         break;
6066 
6067         case GL_TEXTURE_MIN_LOD:
6068         case GL_TEXTURE_MAX_LOD:
6069             // any value is permissible
6070             break;
6071 
6072         case GL_TEXTURE_COMPARE_MODE:
6073             if (!ValidateTextureCompareModeValue(context, params))
6074             {
6075                 return false;
6076             }
6077             break;
6078 
6079         case GL_TEXTURE_COMPARE_FUNC:
6080             if (!ValidateTextureCompareFuncValue(context, params))
6081             {
6082                 return false;
6083             }
6084             break;
6085 
6086         case GL_TEXTURE_SWIZZLE_R:
6087         case GL_TEXTURE_SWIZZLE_G:
6088         case GL_TEXTURE_SWIZZLE_B:
6089         case GL_TEXTURE_SWIZZLE_A:
6090             switch (ConvertToGLenum(params[0]))
6091             {
6092                 case GL_RED:
6093                 case GL_GREEN:
6094                 case GL_BLUE:
6095                 case GL_ALPHA:
6096                 case GL_ZERO:
6097                 case GL_ONE:
6098                     break;
6099 
6100                 default:
6101                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6102                     return false;
6103             }
6104             break;
6105 
6106         case GL_TEXTURE_BASE_LEVEL:
6107             if (ConvertToGLint(params[0]) < 0)
6108             {
6109                 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
6110                 return false;
6111             }
6112             if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
6113             {
6114                 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6115                 return false;
6116             }
6117             if ((target == TextureType::_2DMultisample ||
6118                  target == TextureType::_2DMultisampleArray) &&
6119                 static_cast<GLuint>(params[0]) != 0)
6120             {
6121                 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6122                 return false;
6123             }
6124             if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
6125             {
6126                 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6127                 return false;
6128             }
6129             break;
6130 
6131         case GL_TEXTURE_MAX_LEVEL:
6132             if (ConvertToGLint(params[0]) < 0)
6133             {
6134                 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
6135                 return false;
6136             }
6137             break;
6138 
6139         case GL_DEPTH_STENCIL_TEXTURE_MODE:
6140             if (context->getClientVersion() < Version(3, 1))
6141             {
6142                 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
6143                 return false;
6144             }
6145             switch (ConvertToGLenum(params[0]))
6146             {
6147                 case GL_DEPTH_COMPONENT:
6148                 case GL_STENCIL_INDEX:
6149                     break;
6150 
6151                 default:
6152                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6153                     return false;
6154             }
6155             break;
6156 
6157         case GL_TEXTURE_SRGB_DECODE_EXT:
6158             if (!ValidateTextureSRGBDecodeValue(context, params))
6159             {
6160                 return false;
6161             }
6162             break;
6163 
6164         case GL_GENERATE_MIPMAP:
6165             if (context->getClientMajorVersion() > 1)
6166             {
6167                 context->validationError(GL_INVALID_ENUM, kGLES1Only);
6168                 return false;
6169             }
6170             break;
6171 
6172         case GL_TEXTURE_CROP_RECT_OES:
6173             if (context->getClientMajorVersion() > 1)
6174             {
6175                 context->validationError(GL_INVALID_ENUM, kGLES1Only);
6176                 return false;
6177             }
6178             if (!vectorParams)
6179             {
6180                 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
6181                 return false;
6182             }
6183             break;
6184 
6185         case GL_TEXTURE_BORDER_COLOR:
6186             if (!context->getExtensions().textureBorderClampOES)
6187             {
6188                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6189                 return false;
6190             }
6191             if (!vectorParams)
6192             {
6193                 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
6194                 return false;
6195             }
6196             break;
6197 
6198         default:
6199             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6200             return false;
6201     }
6202 
6203     return true;
6204 }
6205 
6206 template bool ValidateTexParameterBase(const Context *,
6207                                        TextureType,
6208                                        GLenum,
6209                                        GLsizei,
6210                                        bool,
6211                                        const GLfloat *);
6212 template bool ValidateTexParameterBase(const Context *,
6213                                        TextureType,
6214                                        GLenum,
6215                                        GLsizei,
6216                                        bool,
6217                                        const GLint *);
6218 template bool ValidateTexParameterBase(const Context *,
6219                                        TextureType,
6220                                        GLenum,
6221                                        GLsizei,
6222                                        bool,
6223                                        const GLuint *);
6224 
ValidateVertexAttribIndex(const Context * context,GLuint index)6225 bool ValidateVertexAttribIndex(const Context *context, GLuint index)
6226 {
6227     if (index >= MAX_VERTEX_ATTRIBS)
6228     {
6229         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
6230         return false;
6231     }
6232 
6233     return true;
6234 }
6235 
ValidateGetActiveUniformBlockivBase(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLenum pname,GLsizei * length)6236 bool ValidateGetActiveUniformBlockivBase(const Context *context,
6237                                          ShaderProgramID program,
6238                                          GLuint uniformBlockIndex,
6239                                          GLenum pname,
6240                                          GLsizei *length)
6241 {
6242     if (length)
6243     {
6244         *length = 0;
6245     }
6246 
6247     if (context->getClientMajorVersion() < 3)
6248     {
6249         context->validationError(GL_INVALID_OPERATION, kES3Required);
6250         return false;
6251     }
6252 
6253     Program *programObject = GetValidProgram(context, program);
6254     if (!programObject)
6255     {
6256         return false;
6257     }
6258 
6259     if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6260     {
6261         context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
6262         return false;
6263     }
6264 
6265     switch (pname)
6266     {
6267         case GL_UNIFORM_BLOCK_BINDING:
6268         case GL_UNIFORM_BLOCK_DATA_SIZE:
6269         case GL_UNIFORM_BLOCK_NAME_LENGTH:
6270         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6271         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6272         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6273         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6274             break;
6275 
6276         default:
6277             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6278             return false;
6279     }
6280 
6281     if (length)
6282     {
6283         if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6284         {
6285             const InterfaceBlock &uniformBlock =
6286                 programObject->getUniformBlockByIndex(uniformBlockIndex);
6287             *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6288         }
6289         else
6290         {
6291             *length = 1;
6292         }
6293     }
6294 
6295     return true;
6296 }
6297 
6298 template <typename ParamType>
ValidateSamplerParameterBase(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)6299 bool ValidateSamplerParameterBase(const Context *context,
6300                                   SamplerID sampler,
6301                                   GLenum pname,
6302                                   GLsizei bufSize,
6303                                   bool vectorParams,
6304                                   const ParamType *params)
6305 {
6306     if (context->getClientMajorVersion() < 3)
6307     {
6308         context->validationError(GL_INVALID_OPERATION, kES3Required);
6309         return false;
6310     }
6311 
6312     if (!context->isSampler(sampler))
6313     {
6314         context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
6315         return false;
6316     }
6317 
6318     const GLsizei minBufSize = GetSamplerParameterCount(pname);
6319     if (bufSize >= 0 && bufSize < minBufSize)
6320     {
6321         context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
6322         return false;
6323     }
6324 
6325     switch (pname)
6326     {
6327         case GL_TEXTURE_WRAP_S:
6328         case GL_TEXTURE_WRAP_T:
6329         case GL_TEXTURE_WRAP_R:
6330             if (!ValidateTextureWrapModeValue(context, params, false))
6331             {
6332                 return false;
6333             }
6334             break;
6335 
6336         case GL_TEXTURE_MIN_FILTER:
6337             if (!ValidateTextureMinFilterValue(context, params, false))
6338             {
6339                 return false;
6340             }
6341             break;
6342 
6343         case GL_TEXTURE_MAG_FILTER:
6344             if (!ValidateTextureMagFilterValue(context, params))
6345             {
6346                 return false;
6347             }
6348             break;
6349 
6350         case GL_TEXTURE_MIN_LOD:
6351         case GL_TEXTURE_MAX_LOD:
6352             // any value is permissible
6353             break;
6354 
6355         case GL_TEXTURE_COMPARE_MODE:
6356             if (!ValidateTextureCompareModeValue(context, params))
6357             {
6358                 return false;
6359             }
6360             break;
6361 
6362         case GL_TEXTURE_COMPARE_FUNC:
6363             if (!ValidateTextureCompareFuncValue(context, params))
6364             {
6365                 return false;
6366             }
6367             break;
6368 
6369         case GL_TEXTURE_SRGB_DECODE_EXT:
6370             if (!ValidateTextureSRGBDecodeValue(context, params))
6371             {
6372                 return false;
6373             }
6374             break;
6375 
6376         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6377         {
6378             GLfloat paramValue = static_cast<GLfloat>(params[0]);
6379             if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6380             {
6381                 return false;
6382             }
6383         }
6384         break;
6385 
6386         case GL_TEXTURE_BORDER_COLOR:
6387             if (!context->getExtensions().textureBorderClampOES)
6388             {
6389                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6390                 return false;
6391             }
6392             if (!vectorParams)
6393             {
6394                 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
6395                 return false;
6396             }
6397             break;
6398 
6399         default:
6400             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6401             return false;
6402     }
6403 
6404     return true;
6405 }
6406 
6407 template bool ValidateSamplerParameterBase(const Context *,
6408                                            SamplerID,
6409                                            GLenum,
6410                                            GLsizei,
6411                                            bool,
6412                                            const GLfloat *);
6413 template bool ValidateSamplerParameterBase(const Context *,
6414                                            SamplerID,
6415                                            GLenum,
6416                                            GLsizei,
6417                                            bool,
6418                                            const GLint *);
6419 template bool ValidateSamplerParameterBase(const Context *,
6420                                            SamplerID,
6421                                            GLenum,
6422                                            GLsizei,
6423                                            bool,
6424                                            const GLuint *);
6425 
ValidateGetSamplerParameterBase(const Context * context,SamplerID sampler,GLenum pname,GLsizei * length)6426 bool ValidateGetSamplerParameterBase(const Context *context,
6427                                      SamplerID sampler,
6428                                      GLenum pname,
6429                                      GLsizei *length)
6430 {
6431     if (length)
6432     {
6433         *length = 0;
6434     }
6435 
6436     if (context->getClientMajorVersion() < 3)
6437     {
6438         context->validationError(GL_INVALID_OPERATION, kES3Required);
6439         return false;
6440     }
6441 
6442     if (!context->isSampler(sampler))
6443     {
6444         context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
6445         return false;
6446     }
6447 
6448     switch (pname)
6449     {
6450         case GL_TEXTURE_WRAP_S:
6451         case GL_TEXTURE_WRAP_T:
6452         case GL_TEXTURE_WRAP_R:
6453         case GL_TEXTURE_MIN_FILTER:
6454         case GL_TEXTURE_MAG_FILTER:
6455         case GL_TEXTURE_MIN_LOD:
6456         case GL_TEXTURE_MAX_LOD:
6457         case GL_TEXTURE_COMPARE_MODE:
6458         case GL_TEXTURE_COMPARE_FUNC:
6459             break;
6460 
6461         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6462             if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6463             {
6464                 return false;
6465             }
6466             break;
6467 
6468         case GL_TEXTURE_SRGB_DECODE_EXT:
6469             if (!context->getExtensions().textureSRGBDecode)
6470             {
6471                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6472                 return false;
6473             }
6474             break;
6475 
6476         case GL_TEXTURE_BORDER_COLOR:
6477             if (!context->getExtensions().textureBorderClampOES)
6478             {
6479                 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6480                 return false;
6481             }
6482             break;
6483 
6484         default:
6485             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6486             return false;
6487     }
6488 
6489     if (length)
6490     {
6491         *length = GetSamplerParameterCount(pname);
6492     }
6493     return true;
6494 }
6495 
ValidateGetInternalFormativBase(const Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * numParams)6496 bool ValidateGetInternalFormativBase(const Context *context,
6497                                      GLenum target,
6498                                      GLenum internalformat,
6499                                      GLenum pname,
6500                                      GLsizei bufSize,
6501                                      GLsizei *numParams)
6502 {
6503     if (numParams)
6504     {
6505         *numParams = 0;
6506     }
6507 
6508     if (context->getClientMajorVersion() < 3)
6509     {
6510         context->validationError(GL_INVALID_OPERATION, kES3Required);
6511         return false;
6512     }
6513 
6514     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6515     if (!formatCaps.renderbuffer)
6516     {
6517         context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
6518         return false;
6519     }
6520 
6521     switch (target)
6522     {
6523         case GL_RENDERBUFFER:
6524             break;
6525 
6526         case GL_TEXTURE_2D_MULTISAMPLE:
6527             if (context->getClientVersion() < ES_3_1 &&
6528                 !context->getExtensions().textureMultisample)
6529             {
6530                 context->validationError(GL_INVALID_ENUM,
6531                                          kMultisampleTextureExtensionOrES31Required);
6532                 return false;
6533             }
6534             break;
6535         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6536             if (!context->getExtensions().textureStorageMultisample2DArrayOES)
6537             {
6538                 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
6539                 return false;
6540             }
6541             break;
6542         default:
6543             context->validationError(GL_INVALID_ENUM, kInvalidTarget);
6544             return false;
6545     }
6546 
6547     if (bufSize < 0)
6548     {
6549         context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
6550         return false;
6551     }
6552 
6553     GLsizei maxWriteParams = 0;
6554     switch (pname)
6555     {
6556         case GL_NUM_SAMPLE_COUNTS:
6557             maxWriteParams = 1;
6558             break;
6559 
6560         case GL_SAMPLES:
6561             maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6562             break;
6563 
6564         default:
6565             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6566             return false;
6567     }
6568 
6569     if (numParams)
6570     {
6571         // glGetInternalFormativ will not overflow bufSize
6572         *numParams = std::min(bufSize, maxWriteParams);
6573     }
6574 
6575     return true;
6576 }
6577 
ValidateFramebufferNotMultisampled(const Context * context,const Framebuffer * framebuffer,bool needResourceSamples)6578 bool ValidateFramebufferNotMultisampled(const Context *context,
6579                                         const Framebuffer *framebuffer,
6580                                         bool needResourceSamples)
6581 {
6582     int samples = needResourceSamples ? framebuffer->getResourceSamples(context)
6583                                       : framebuffer->getSamples(context);
6584     if (samples != 0)
6585     {
6586         context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
6587         return false;
6588     }
6589     return true;
6590 }
6591 
ValidateMultitextureUnit(const Context * context,GLenum texture)6592 bool ValidateMultitextureUnit(const Context *context, GLenum texture)
6593 {
6594     if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6595     {
6596         context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
6597         return false;
6598     }
6599     return true;
6600 }
6601 
ValidateTexStorageMultisample(const Context * context,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)6602 bool ValidateTexStorageMultisample(const Context *context,
6603                                    TextureType target,
6604                                    GLsizei samples,
6605                                    GLint internalFormat,
6606                                    GLsizei width,
6607                                    GLsizei height)
6608 {
6609     const Caps &caps = context->getCaps();
6610     if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
6611     {
6612         context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
6613         return false;
6614     }
6615 
6616     if (samples == 0)
6617     {
6618         context->validationError(GL_INVALID_VALUE, kSamplesZero);
6619         return false;
6620     }
6621 
6622     const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6623     if (!formatCaps.textureAttachment)
6624     {
6625         context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
6626         return false;
6627     }
6628 
6629     // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6630     // is one of the unsized base internalformats listed in table 8.11.
6631     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6632     if (formatInfo.internalFormat == GL_NONE)
6633     {
6634         context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
6635         return false;
6636     }
6637 
6638     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6639     {
6640         context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
6641         return false;
6642     }
6643 
6644     Texture *texture = context->getTextureByType(target);
6645     if (!texture || texture->id().value == 0)
6646     {
6647         context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
6648         return false;
6649     }
6650 
6651     if (texture->getImmutableFormat())
6652     {
6653         context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
6654         return false;
6655     }
6656     return true;
6657 }
6658 
ValidateTexStorage2DMultisampleBase(const Context * context,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)6659 bool ValidateTexStorage2DMultisampleBase(const Context *context,
6660                                          TextureType target,
6661                                          GLsizei samples,
6662                                          GLint internalFormat,
6663                                          GLsizei width,
6664                                          GLsizei height)
6665 {
6666     if (target != TextureType::_2DMultisample)
6667     {
6668         context->validationError(GL_INVALID_ENUM, kInvalidTarget);
6669         return false;
6670     }
6671 
6672     if (width < 1 || height < 1)
6673     {
6674         context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
6675         return false;
6676     }
6677 
6678     return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6679 }
6680 
ValidateGetTexLevelParameterBase(const Context * context,TextureTarget target,GLint level,GLenum pname,GLsizei * length)6681 bool ValidateGetTexLevelParameterBase(const Context *context,
6682                                       TextureTarget target,
6683                                       GLint level,
6684                                       GLenum pname,
6685                                       GLsizei *length)
6686 {
6687 
6688     if (length)
6689     {
6690         *length = 0;
6691     }
6692 
6693     TextureType type = TextureTargetToType(target);
6694 
6695     if (!ValidTexLevelDestinationTarget(context, type))
6696     {
6697         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6698         return false;
6699     }
6700 
6701     if (context->getTextureByType(type) == nullptr)
6702     {
6703         context->validationError(GL_INVALID_ENUM, kTextureNotBound);
6704         return false;
6705     }
6706 
6707     if (!ValidMipLevel(context, type, level))
6708     {
6709         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
6710         return false;
6711     }
6712 
6713     switch (pname)
6714     {
6715         case GL_TEXTURE_RED_TYPE:
6716         case GL_TEXTURE_GREEN_TYPE:
6717         case GL_TEXTURE_BLUE_TYPE:
6718         case GL_TEXTURE_ALPHA_TYPE:
6719         case GL_TEXTURE_DEPTH_TYPE:
6720             break;
6721         case GL_TEXTURE_RED_SIZE:
6722         case GL_TEXTURE_GREEN_SIZE:
6723         case GL_TEXTURE_BLUE_SIZE:
6724         case GL_TEXTURE_ALPHA_SIZE:
6725         case GL_TEXTURE_DEPTH_SIZE:
6726         case GL_TEXTURE_STENCIL_SIZE:
6727         case GL_TEXTURE_SHARED_SIZE:
6728             break;
6729         case GL_TEXTURE_INTERNAL_FORMAT:
6730         case GL_TEXTURE_WIDTH:
6731         case GL_TEXTURE_HEIGHT:
6732         case GL_TEXTURE_DEPTH:
6733             break;
6734         case GL_TEXTURE_SAMPLES:
6735         case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6736             break;
6737         case GL_TEXTURE_COMPRESSED:
6738             break;
6739         default:
6740             context->validationError(GL_INVALID_ENUM, kInvalidPname);
6741             return false;
6742     }
6743 
6744     if (length)
6745     {
6746         *length = 1;
6747     }
6748     return true;
6749 }
6750 
ValidateGetMultisamplefvBase(const Context * context,GLenum pname,GLuint index,const GLfloat * val)6751 bool ValidateGetMultisamplefvBase(const Context *context,
6752                                   GLenum pname,
6753                                   GLuint index,
6754                                   const GLfloat *val)
6755 {
6756     if (pname != GL_SAMPLE_POSITION)
6757     {
6758         context->validationError(GL_INVALID_ENUM, kInvalidPname);
6759         return false;
6760     }
6761 
6762     Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
6763     GLint samples            = framebuffer->getSamples(context);
6764 
6765     if (index >= static_cast<GLuint>(samples))
6766     {
6767         context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6768         return false;
6769     }
6770 
6771     return true;
6772 }
6773 
ValidateSampleMaskiBase(const Context * context,GLuint maskNumber,GLbitfield mask)6774 bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask)
6775 {
6776     if (maskNumber >= static_cast<GLuint>(context->getCaps().maxSampleMaskWords))
6777     {
6778         context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6779         return false;
6780     }
6781 
6782     return true;
6783 }
6784 
RecordDrawAttribsError(const Context * context)6785 void RecordDrawAttribsError(const Context *context)
6786 {
6787     // An overflow can happen when adding the offset. Check against a special constant.
6788     if (context->getStateCache().getNonInstancedVertexElementLimit() ==
6789             VertexAttribute::kIntegerOverflow ||
6790         context->getStateCache().getInstancedVertexElementLimit() ==
6791             VertexAttribute::kIntegerOverflow)
6792     {
6793         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
6794     }
6795     else
6796     {
6797         // [OpenGL ES 3.0.2] section 2.9.4 page 40:
6798         // We can return INVALID_OPERATION if our buffer does not have enough backing data.
6799         context->validationError(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
6800     }
6801 }
6802 
ValidateLoseContextCHROMIUM(const Context * context,GraphicsResetStatus current,GraphicsResetStatus other)6803 bool ValidateLoseContextCHROMIUM(const Context *context,
6804                                  GraphicsResetStatus current,
6805                                  GraphicsResetStatus other)
6806 {
6807     if (!context->getExtensions().loseContextCHROMIUM)
6808     {
6809         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6810         return false;
6811     }
6812 
6813     switch (current)
6814     {
6815         case GraphicsResetStatus::GuiltyContextReset:
6816         case GraphicsResetStatus::InnocentContextReset:
6817         case GraphicsResetStatus::UnknownContextReset:
6818             break;
6819 
6820         default:
6821             context->validationError(GL_INVALID_ENUM, kInvalidResetStatus);
6822     }
6823 
6824     switch (other)
6825     {
6826         case GraphicsResetStatus::GuiltyContextReset:
6827         case GraphicsResetStatus::InnocentContextReset:
6828         case GraphicsResetStatus::UnknownContextReset:
6829             break;
6830 
6831         default:
6832             context->validationError(GL_INVALID_ENUM, kInvalidResetStatus);
6833     }
6834 
6835     return true;
6836 }
6837 
6838 // GL_ANGLE_texture_storage_external
ValidateTexImage2DExternalANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type)6839 bool ValidateTexImage2DExternalANGLE(const Context *context,
6840                                      TextureTarget target,
6841                                      GLint level,
6842                                      GLint internalformat,
6843                                      GLsizei width,
6844                                      GLsizei height,
6845                                      GLint border,
6846                                      GLenum format,
6847                                      GLenum type)
6848 {
6849     if (!context->getExtensions().textureExternalUpdateANGLE)
6850     {
6851         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6852         return false;
6853     }
6854 
6855     if (!ValidTexture2DDestinationTarget(context, target) &&
6856         !ValidTextureExternalTarget(context, target))
6857     {
6858         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6859         return false;
6860     }
6861 
6862     if (context->getClientMajorVersion() <= 2)
6863     {
6864         if (!ValidateES2TexImageParametersBase(context, target, level, internalformat, false, false,
6865                                                0, 0, width, height, border, format, type, -1,
6866                                                nullptr))
6867         {
6868             return false;
6869         }
6870     }
6871     else
6872     {
6873         if (!ValidateES3TexImageParametersBase(context, target, level, internalformat, false, false,
6874                                                0, 0, 0, width, height, 1, border, format, type, -1,
6875                                                nullptr))
6876         {
6877             return false;
6878         }
6879     }
6880 
6881     return true;
6882 }
6883 
ValidateInvalidateTextureANGLE(const Context * context,TextureType target)6884 bool ValidateInvalidateTextureANGLE(const Context *context, TextureType target)
6885 {
6886     if (!context->getExtensions().textureExternalUpdateANGLE)
6887     {
6888         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6889         return false;
6890     }
6891 
6892     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
6893     {
6894         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6895         return false;
6896     }
6897 
6898     return true;
6899 }
6900 
6901 }  // namespace gl
6902