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