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