• 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 }
74 
DifferenceCanOverflow(GLint a,GLint b)75 bool DifferenceCanOverflow(GLint a, GLint b)
76 {
77     CheckedNumeric<GLint> checkedA(a);
78     checkedA -= b;
79     // Use negation to make sure that the difference can't overflow regardless of the order.
80     checkedA = -checkedA;
81     return !checkedA.IsValid();
82 }
83 
ValidReadPixelsTypeEnum(const Context * context,GLenum type)84 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
85 {
86     switch (type)
87     {
88         // Types referenced in Table 3.4 of the ES 2.0.25 spec
89         case GL_UNSIGNED_BYTE:
90         case GL_UNSIGNED_SHORT_4_4_4_4:
91         case GL_UNSIGNED_SHORT_5_5_5_1:
92         case GL_UNSIGNED_SHORT_5_6_5:
93             return context->getClientVersion() >= ES_2_0;
94 
95         // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
96         case GL_BYTE:
97         case GL_INT:
98         case GL_SHORT:
99         case GL_UNSIGNED_INT:
100         case GL_UNSIGNED_INT_10F_11F_11F_REV:
101         case GL_UNSIGNED_INT_2_10_10_10_REV:
102         case GL_UNSIGNED_INT_5_9_9_9_REV:
103         case GL_UNSIGNED_SHORT:
104         case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
105         case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
106             return context->getClientVersion() >= ES_3_0;
107 
108         case GL_FLOAT:
109             return context->getClientVersion() >= ES_3_0 ||
110                    context->getExtensions().textureFloatOES ||
111                    context->getExtensions().colorBufferHalfFloatEXT;
112 
113         case GL_HALF_FLOAT:
114             return context->getClientVersion() >= ES_3_0 ||
115                    context->getExtensions().textureHalfFloatOES;
116 
117         case GL_HALF_FLOAT_OES:
118             return context->getExtensions().colorBufferHalfFloatEXT;
119 
120         default:
121             return false;
122     }
123 }
124 
ValidReadPixelsFormatEnum(const Context * context,GLenum format)125 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
126 {
127     switch (format)
128     {
129         // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
130         case GL_RGBA:
131         case GL_RGB:
132         case GL_ALPHA:
133             return context->getClientVersion() >= ES_2_0;
134 
135         // Formats referenced in Table 3.2 of the ES 3.0.5 spec
136         case GL_RG:
137         case GL_RED:
138         case GL_RGBA_INTEGER:
139         case GL_RGB_INTEGER:
140         case GL_RG_INTEGER:
141         case GL_RED_INTEGER:
142             return context->getClientVersion() >= ES_3_0;
143 
144         case GL_SRGB_ALPHA_EXT:
145         case GL_SRGB_EXT:
146             return context->getExtensions().sRGBEXT;
147 
148         case GL_BGRA_EXT:
149             return context->getExtensions().readFormatBgraEXT;
150 
151         case GL_RGBX8_ANGLE:
152             return context->getExtensions().rgbxInternalFormatANGLE;
153 
154         default:
155             return false;
156     }
157 }
158 
ValidReadPixelsUnsignedNormalizedDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)159 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
160                                                 const gl::InternalFormat *info,
161                                                 GLenum type)
162 {
163     bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0);
164     switch (type)
165     {
166         case GL_UNSIGNED_SHORT:
167         case GL_UNSIGNED_INT:
168         case GL_UNSIGNED_INT_24_8:
169             return supportsReadDepthNV;
170         default:
171             return false;
172     }
173 }
174 
ValidReadPixelsFloatDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)175 bool ValidReadPixelsFloatDepthType(const Context *context,
176                                    const gl::InternalFormat *info,
177                                    GLenum type)
178 {
179     return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
180            context->getExtensions().depthBufferFloat2NV;
181 }
182 
ValidReadPixelsFormatType(const Context * context,const gl::InternalFormat * info,GLenum format,GLenum type)183 bool ValidReadPixelsFormatType(const Context *context,
184                                const gl::InternalFormat *info,
185                                GLenum format,
186                                GLenum type)
187 {
188     switch (info->componentType)
189     {
190         case GL_UNSIGNED_NORMALIZED:
191             // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
192             // ReadPixels with BGRA even if the extension is not present
193             switch (format)
194             {
195                 case GL_RGBA:
196                     return type == GL_UNSIGNED_BYTE ||
197                            (context->getExtensions().textureNorm16EXT &&
198                             type == GL_UNSIGNED_SHORT && info->type == GL_UNSIGNED_SHORT);
199                 case GL_BGRA_EXT:
200                     return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE);
201                 case GL_STENCIL_INDEX_OES:
202                     return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
203                 case GL_DEPTH_COMPONENT:
204                     return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
205                 case GL_DEPTH_STENCIL_OES:
206                     return context->getExtensions().readDepthStencilNV &&
207                            (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0;
208                 case GL_RGBX8_ANGLE:
209                     return context->getExtensions().rgbxInternalFormatANGLE &&
210                            (type == GL_UNSIGNED_BYTE);
211                 default:
212                     return false;
213             }
214         case GL_SIGNED_NORMALIZED:
215             ASSERT(context->getExtensions().renderSnormEXT);
216             ASSERT(info->type == GL_BYTE ||
217                    (context->getExtensions().textureNorm16EXT && info->type == GL_SHORT));
218             // Type conversions are not allowed for signed normalized color buffers
219             return format == GL_RGBA && type == info->type;
220 
221         case GL_INT:
222             return (format == GL_RGBA_INTEGER && type == GL_INT);
223 
224         case GL_UNSIGNED_INT:
225             return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
226 
227         case GL_FLOAT:
228             switch (format)
229             {
230                 case GL_RGBA:
231                     return (type == GL_FLOAT);
232                 case GL_DEPTH_COMPONENT:
233                     return ValidReadPixelsFloatDepthType(context, info, type);
234                 case GL_DEPTH_STENCIL_OES:
235                     return context->getExtensions().readDepthStencilNV &&
236                            type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0;
237                 default:
238                     return false;
239             }
240         default:
241             UNREACHABLE();
242             return false;
243     }
244 }
245 
246 template <typename ParamType>
ValidateTextureWrapModeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params,bool restrictedWrapModes)247 bool ValidateTextureWrapModeValue(const Context *context,
248                                   angle::EntryPoint entryPoint,
249                                   const ParamType *params,
250                                   bool restrictedWrapModes)
251 {
252     switch (ConvertToGLenum(params[0]))
253     {
254         case GL_CLAMP_TO_EDGE:
255             break;
256 
257         case GL_CLAMP_TO_BORDER:
258             if (!context->getExtensions().textureBorderClampAny() &&
259                 context->getClientVersion() < ES_3_2)
260             {
261                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
262                 return false;
263             }
264             if (restrictedWrapModes)
265             {
266                 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
267                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
268                 return false;
269             }
270             break;
271 
272         case GL_REPEAT:
273         case GL_MIRRORED_REPEAT:
274             if (restrictedWrapModes)
275             {
276                 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
277                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
278                 return false;
279             }
280             break;
281 
282         case GL_MIRROR_CLAMP_TO_EDGE_EXT:
283             if (!context->getExtensions().textureMirrorClampToEdgeEXT)
284             {
285                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
286                 return false;
287             }
288             if (restrictedWrapModes)
289             {
290                 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
291                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
292                 return false;
293             }
294             break;
295 
296         default:
297             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureWrap);
298             return false;
299     }
300 
301     return true;
302 }
303 
304 template <typename ParamType>
ValidateTextureMinFilterValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params,bool restrictedMinFilter)305 bool ValidateTextureMinFilterValue(const Context *context,
306                                    angle::EntryPoint entryPoint,
307                                    const ParamType *params,
308                                    bool restrictedMinFilter)
309 {
310     switch (ConvertToGLenum(params[0]))
311     {
312         case GL_NEAREST:
313         case GL_LINEAR:
314             break;
315 
316         case GL_NEAREST_MIPMAP_NEAREST:
317         case GL_LINEAR_MIPMAP_NEAREST:
318         case GL_NEAREST_MIPMAP_LINEAR:
319         case GL_LINEAR_MIPMAP_LINEAR:
320             if (restrictedMinFilter)
321             {
322                 // OES_EGL_image_external specifies this error.
323                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFilterTexture);
324                 return false;
325             }
326             break;
327 
328         default:
329             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureFilterParam);
330             return false;
331     }
332 
333     return true;
334 }
335 
336 template <typename ParamType>
ValidateTextureMagFilterValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)337 bool ValidateTextureMagFilterValue(const Context *context,
338                                    angle::EntryPoint entryPoint,
339                                    const ParamType *params)
340 {
341     switch (ConvertToGLenum(params[0]))
342     {
343         case GL_NEAREST:
344         case GL_LINEAR:
345             break;
346 
347         default:
348             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureFilterParam);
349             return false;
350     }
351 
352     return true;
353 }
354 
355 template <typename ParamType>
ValidateTextureCompareModeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)356 bool ValidateTextureCompareModeValue(const Context *context,
357                                      angle::EntryPoint entryPoint,
358                                      const ParamType *params)
359 {
360     // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
361     switch (ConvertToGLenum(params[0]))
362     {
363         case GL_NONE:
364         case GL_COMPARE_REF_TO_TEXTURE:
365             break;
366 
367         default:
368             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
369             return false;
370     }
371 
372     return true;
373 }
374 
375 template <typename ParamType>
ValidateTextureCompareFuncValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)376 bool ValidateTextureCompareFuncValue(const Context *context,
377                                      angle::EntryPoint entryPoint,
378                                      const ParamType *params)
379 {
380     // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
381     switch (ConvertToGLenum(params[0]))
382     {
383         case GL_LEQUAL:
384         case GL_GEQUAL:
385         case GL_LESS:
386         case GL_GREATER:
387         case GL_EQUAL:
388         case GL_NOTEQUAL:
389         case GL_ALWAYS:
390         case GL_NEVER:
391             break;
392 
393         default:
394             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
395             return false;
396     }
397 
398     return true;
399 }
400 
401 template <typename ParamType>
ValidateTextureSRGBDecodeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)402 bool ValidateTextureSRGBDecodeValue(const Context *context,
403                                     angle::EntryPoint entryPoint,
404                                     const ParamType *params)
405 {
406     if (!context->getExtensions().textureSRGBDecodeEXT)
407     {
408         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
409         return false;
410     }
411 
412     switch (ConvertToGLenum(params[0]))
413     {
414         case GL_DECODE_EXT:
415         case GL_SKIP_DECODE_EXT:
416             break;
417 
418         default:
419             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
420             return false;
421     }
422 
423     return true;
424 }
425 
426 template <typename ParamType>
ValidateTextureSRGBOverrideValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)427 bool ValidateTextureSRGBOverrideValue(const Context *context,
428                                       angle::EntryPoint entryPoint,
429                                       const ParamType *params)
430 {
431     if (!context->getExtensions().textureFormatSRGBOverrideEXT)
432     {
433         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
434         return false;
435     }
436 
437     switch (ConvertToGLenum(params[0]))
438     {
439         case GL_SRGB:
440         case GL_NONE:
441             break;
442 
443         default:
444             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
445             return false;
446     }
447 
448     return true;
449 }
450 
ValidateTextureMaxAnisotropyExtensionEnabled(const Context * context,angle::EntryPoint entryPoint)451 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context,
452                                                   angle::EntryPoint entryPoint)
453 {
454     if (!context->getExtensions().textureFilterAnisotropicEXT)
455     {
456         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
457         return false;
458     }
459 
460     return true;
461 }
462 
ValidateTextureMaxAnisotropyValue(const Context * context,angle::EntryPoint entryPoint,GLfloat paramValue)463 bool ValidateTextureMaxAnisotropyValue(const Context *context,
464                                        angle::EntryPoint entryPoint,
465                                        GLfloat paramValue)
466 {
467     if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
468     {
469         return false;
470     }
471 
472     GLfloat largest = context->getCaps().maxTextureAnisotropy;
473 
474     if (paramValue < 1 || paramValue > largest)
475     {
476         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOutsideOfBounds);
477         return false;
478     }
479 
480     return true;
481 }
482 
ValidateFragmentShaderColorBufferMaskMatch(const Context * context)483 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
484 {
485     const auto &glState            = context->getState();
486     const Program *program         = context->getActiveLinkedProgram();
487     const Framebuffer *framebuffer = glState.getDrawFramebuffer();
488 
489     auto drawBufferMask =
490         framebuffer->getDrawBufferMask() & glState.getBlendStateExt().compareColorMask(0);
491     auto fragmentOutputMask = program->getExecutable().getActiveOutputVariablesMask();
492 
493     return drawBufferMask == (drawBufferMask & fragmentOutputMask);
494 }
495 
ValidateFragmentShaderColorBufferTypeMatch(const Context * context)496 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
497 {
498     const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
499     const Framebuffer *framebuffer      = context->getState().getDrawFramebuffer();
500 
501     return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(),
502                                       framebuffer->getDrawBufferTypeMask().to_ulong(),
503                                       executable->getActiveOutputVariablesMask().to_ulong(),
504                                       framebuffer->getDrawBufferMask().to_ulong());
505 }
506 
ValidateVertexShaderAttributeTypeMatch(const Context * context)507 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
508 {
509     const auto &glState    = context->getState();
510     const Program *program = context->getActiveLinkedProgram();
511     const VertexArray *vao = context->getState().getVertexArray();
512 
513     if (!program)
514     {
515         return false;
516     }
517 
518     unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
519     unsigned long vaoAttribTypeBits          = vao->getAttributesTypeMask().to_ulong();
520     unsigned long vaoAttribEnabledMask       = vao->getAttributesMask().to_ulong();
521 
522     vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
523     vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
524     vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
525 
526     const ProgramExecutable &executable = program->getExecutable();
527     return ValidateComponentTypeMasks(executable.getAttributesTypeMask().to_ulong(),
528                                       vaoAttribTypeBits, executable.getAttributesMask().to_ulong(),
529                                       0xFFFF);
530 }
531 
IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,PrimitiveMode geometryShaderInputPrimitiveType)532 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
533                                             PrimitiveMode geometryShaderInputPrimitiveType)
534 {
535     // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
536     switch (drawMode)
537     {
538         case PrimitiveMode::Points:
539             return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
540         case PrimitiveMode::Lines:
541         case PrimitiveMode::LineStrip:
542         case PrimitiveMode::LineLoop:
543             return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
544         case PrimitiveMode::LinesAdjacency:
545         case PrimitiveMode::LineStripAdjacency:
546             return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
547         case PrimitiveMode::Triangles:
548         case PrimitiveMode::TriangleFan:
549         case PrimitiveMode::TriangleStrip:
550             return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
551         case PrimitiveMode::TrianglesAdjacency:
552         case PrimitiveMode::TriangleStripAdjacency:
553             return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
554         default:
555             UNREACHABLE();
556             return false;
557     }
558 }
559 
560 // GLES1 texture parameters are a small subset of the others
IsValidGLES1TextureParameter(GLenum pname)561 bool IsValidGLES1TextureParameter(GLenum pname)
562 {
563     switch (pname)
564     {
565         case GL_TEXTURE_MAG_FILTER:
566         case GL_TEXTURE_MIN_FILTER:
567         case GL_TEXTURE_WRAP_S:
568         case GL_TEXTURE_WRAP_T:
569         case GL_TEXTURE_WRAP_R:
570         case GL_GENERATE_MIPMAP:
571         case GL_TEXTURE_CROP_RECT_OES:
572             return true;
573         default:
574             return false;
575     }
576 }
577 
GetSamplerParameterCount(GLenum pname)578 unsigned int GetSamplerParameterCount(GLenum pname)
579 {
580     return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
581 }
582 
ValidateProgramDrawAdvancedBlendState(const Context * context,Program * program)583 const char *ValidateProgramDrawAdvancedBlendState(const Context *context, Program *program)
584 {
585     const State &state = context->getState();
586     const BlendEquationBitSet &supportedBlendEquations =
587         program->getExecutable().getAdvancedBlendEquations();
588     const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask();
589 
590     for (size_t blendEnabledBufferIndex : enabledDrawBufferMask)
591     {
592         const gl::BlendEquationType &enabledBlendEquation = gl::FromGLenum<gl::BlendEquationType>(
593             state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex));
594 
595         if (enabledBlendEquation < gl::BlendEquationType::Multiply ||
596             enabledBlendEquation > gl::BlendEquationType::HslLuminosity)
597         {
598             continue;
599         }
600 
601         if (!supportedBlendEquations.test(enabledBlendEquation))
602         {
603             return gl::err::kBlendEquationNotEnabled;
604         }
605     }
606 
607     return nullptr;
608 }
609 
ValidateProgramDrawStates(const Context * context,const Extensions & extensions,Program * program)610 ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context,
611                                                    const Extensions &extensions,
612                                                    Program *program)
613 {
614     const State &state = context->getState();
615     if (extensions.multiviewOVR || extensions.multiview2OVR)
616     {
617         const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
618         Framebuffer *framebuffer      = state.getDrawFramebuffer();
619         const int framebufferNumViews = framebuffer->getNumViews();
620 
621         if (framebufferNumViews != programNumViews)
622         {
623             return gl::err::kMultiviewMismatch;
624         }
625 
626         if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
627         {
628             return gl::err::kMultiviewTransformFeedback;
629         }
630 
631         if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 &&
632             state.isQueryActive(QueryType::TimeElapsed))
633         {
634             return gl::err::kMultiviewTimerQuery;
635         }
636     }
637 
638     // Uniform buffer validation
639     for (unsigned int uniformBlockIndex = 0;
640          uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
641     {
642         const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
643         GLuint blockBinding                = program->getUniformBlockBinding(uniformBlockIndex);
644         const OffsetBindingPointer<Buffer> &uniformBuffer =
645             state.getIndexedUniformBuffer(blockBinding);
646 
647         if (uniformBuffer.get() == nullptr && context->isWebGL())
648         {
649             // undefined behaviour
650             return gl::err::kUniformBufferUnbound;
651         }
652 
653         size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
654         if (uniformBufferSize < uniformBlock.dataSize &&
655             (context->isWebGL() || context->isBufferAccessValidationEnabled()))
656         {
657             // undefined behaviour
658             return gl::err::kUniformBufferTooSmall;
659         }
660 
661         if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
662         {
663             return gl::err::kUniformBufferBoundForTransformFeedback;
664         }
665     }
666 
667     // Enabled blend equation validation
668     const char *errorString = nullptr;
669 
670     if (extensions.blendEquationAdvancedKHR)
671     {
672         errorString = ValidateProgramDrawAdvancedBlendState(context, program);
673     }
674 
675     return errorString;
676 }
677 }  // anonymous namespace
678 
SetRobustLengthParam(const GLsizei * length,GLsizei value)679 void SetRobustLengthParam(const GLsizei *length, GLsizei value)
680 {
681     if (length)
682     {
683         // Currently we modify robust length parameters in the validation layer. We should be only
684         // doing this in the Context instead.
685         // TODO(http://anglebug.com/4406): Remove when possible.
686         *const_cast<GLsizei *>(length) = value;
687     }
688 }
689 
ValidTextureTarget(const Context * context,TextureType type)690 bool ValidTextureTarget(const Context *context, TextureType type)
691 {
692     switch (type)
693     {
694         case TextureType::_2D:
695         case TextureType::CubeMap:
696             return true;
697 
698         case TextureType::Rectangle:
699             return context->getExtensions().textureRectangleANGLE;
700 
701         case TextureType::_3D:
702             return ((context->getClientMajorVersion() >= 3) ||
703                     context->getExtensions().texture3DOES);
704 
705         case TextureType::_2DArray:
706             return (context->getClientMajorVersion() >= 3);
707 
708         case TextureType::_2DMultisample:
709             return (context->getClientVersion() >= Version(3, 1) ||
710                     context->getExtensions().textureMultisampleANGLE);
711         case TextureType::_2DMultisampleArray:
712             return context->getExtensions().textureStorageMultisample2dArrayOES;
713 
714         case TextureType::CubeMapArray:
715             return (context->getClientVersion() >= Version(3, 2) ||
716                     context->getExtensions().textureCubeMapArrayAny());
717 
718         case TextureType::VideoImage:
719             return context->getExtensions().videoTextureWEBGL;
720 
721         case TextureType::Buffer:
722             return (context->getClientVersion() >= Version(3, 2) ||
723                     context->getExtensions().textureBufferAny());
724 
725         default:
726             return false;
727     }
728 }
729 
ValidTexture2DTarget(const Context * context,TextureType type)730 bool ValidTexture2DTarget(const Context *context, TextureType type)
731 {
732     switch (type)
733     {
734         case TextureType::_2D:
735         case TextureType::CubeMap:
736             return true;
737 
738         case TextureType::Rectangle:
739             return context->getExtensions().textureRectangleANGLE;
740 
741         default:
742             return false;
743     }
744 }
745 
ValidTexture3DTarget(const Context * context,TextureType target)746 bool ValidTexture3DTarget(const Context *context, TextureType target)
747 {
748     switch (target)
749     {
750         case TextureType::_3D:
751         case TextureType::_2DArray:
752             return (context->getClientMajorVersion() >= 3);
753 
754         case TextureType::CubeMapArray:
755             return (context->getClientVersion() >= Version(3, 2) ||
756                     context->getExtensions().textureCubeMapArrayAny());
757 
758         default:
759             return false;
760     }
761 }
762 
763 // Most texture GL calls are not compatible with external textures, so we have a separate validation
764 // function for use in the GL calls that do
ValidTextureExternalTarget(const Context * context,TextureType target)765 bool ValidTextureExternalTarget(const Context *context, TextureType target)
766 {
767     return (target == TextureType::External) &&
768            (context->getExtensions().EGLImageExternalOES ||
769             context->getExtensions().EGLStreamConsumerExternalNV);
770 }
771 
ValidTextureExternalTarget(const Context * context,TextureTarget target)772 bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
773 {
774     return (target == TextureTarget::External) &&
775            ValidTextureExternalTarget(context, TextureType::External);
776 }
777 
778 // This function differs from ValidTextureTarget in that the target must be
779 // usable as the destination of a 2D operation-- so a cube face is valid, but
780 // GL_TEXTURE_CUBE_MAP is not.
781 // Note: duplicate of IsInternalTextureTarget
ValidTexture2DDestinationTarget(const Context * context,TextureTarget target)782 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
783 {
784     switch (target)
785     {
786         case TextureTarget::_2D:
787         case TextureTarget::CubeMapNegativeX:
788         case TextureTarget::CubeMapNegativeY:
789         case TextureTarget::CubeMapNegativeZ:
790         case TextureTarget::CubeMapPositiveX:
791         case TextureTarget::CubeMapPositiveY:
792         case TextureTarget::CubeMapPositiveZ:
793             return true;
794         case TextureTarget::Rectangle:
795             return context->getExtensions().textureRectangleANGLE;
796         case TextureTarget::VideoImage:
797             return context->getExtensions().videoTextureWEBGL;
798         default:
799             return false;
800     }
801 }
802 
ValidateTransformFeedbackPrimitiveMode(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode transformFeedbackPrimitiveMode,PrimitiveMode renderPrimitiveMode)803 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
804                                             angle::EntryPoint entryPoint,
805                                             PrimitiveMode transformFeedbackPrimitiveMode,
806                                             PrimitiveMode renderPrimitiveMode)
807 {
808     ASSERT(context);
809 
810     if ((!context->getExtensions().geometryShaderAny() ||
811          !context->getExtensions().tessellationShaderEXT) &&
812         context->getClientVersion() < ES_3_2)
813     {
814         // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
815         // that does not match the current transform feedback object's draw mode (if transform
816         // feedback is active), (3.0.2, section 2.14, pg 86)
817         return transformFeedbackPrimitiveMode == renderPrimitiveMode;
818     }
819 
820     const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
821     ASSERT(executable);
822     if (executable->hasLinkedShaderStage(ShaderType::Geometry))
823     {
824         // If geometry shader is active, transform feedback mode must match what is output from this
825         // stage.
826         renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType();
827     }
828     else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
829     {
830         // Similarly with tessellation shaders, but only if no geometry shader is present.  With
831         // tessellation shaders, only triangles are possibly output.
832         return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles &&
833                executable->getTessGenMode() == GL_TRIANGLES;
834     }
835 
836     // [GL_EXT_geometry_shader] Table 12.1gs
837     switch (renderPrimitiveMode)
838     {
839         case PrimitiveMode::Points:
840             return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
841         case PrimitiveMode::Lines:
842         case PrimitiveMode::LineStrip:
843         case PrimitiveMode::LineLoop:
844             return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
845         case PrimitiveMode::Triangles:
846         case PrimitiveMode::TriangleFan:
847         case PrimitiveMode::TriangleStrip:
848             return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
849         case PrimitiveMode::Patches:
850             return transformFeedbackPrimitiveMode == PrimitiveMode::Patches;
851         default:
852             UNREACHABLE();
853             return false;
854     }
855 }
856 
ValidateDrawElementsInstancedBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)857 bool ValidateDrawElementsInstancedBase(const Context *context,
858                                        angle::EntryPoint entryPoint,
859                                        PrimitiveMode mode,
860                                        GLsizei count,
861                                        DrawElementsType type,
862                                        const void *indices,
863                                        GLsizei primcount)
864 {
865     if (primcount <= 0)
866     {
867         if (primcount < 0)
868         {
869             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
870             return false;
871         }
872 
873         // Early exit.
874         return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices,
875                                           primcount);
876     }
877 
878     if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount))
879     {
880         return false;
881     }
882 
883     if (count == 0)
884     {
885         // Early exit.
886         return true;
887     }
888 
889     return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
890 }
891 
ValidateDrawArraysInstancedBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)892 bool ValidateDrawArraysInstancedBase(const Context *context,
893                                      angle::EntryPoint entryPoint,
894                                      PrimitiveMode mode,
895                                      GLint first,
896                                      GLsizei count,
897                                      GLsizei primcount)
898 {
899     if (primcount <= 0)
900     {
901         if (primcount < 0)
902         {
903             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
904             return false;
905         }
906 
907         // Early exit.
908         return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount);
909     }
910 
911     if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount))
912     {
913         return false;
914     }
915 
916     if (count == 0)
917     {
918         // Early exit.
919         return true;
920     }
921 
922     return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
923 }
924 
ValidateDrawInstancedANGLE(const Context * context,angle::EntryPoint entryPoint)925 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint)
926 {
927     // Verify there is at least one active attribute with a divisor of zero
928     const State &state                  = context->getState();
929     const ProgramExecutable *executable = state.getLinkedProgramExecutable(context);
930 
931     if (!executable)
932     {
933         // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
934         // an error.
935         context->getState().getDebug().insertMessage(
936             GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
937             std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint);
938         return true;
939     }
940 
941     const auto &attribs  = state.getVertexArray()->getVertexAttributes();
942     const auto &bindings = state.getVertexArray()->getVertexBindings();
943     for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++)
944     {
945         const VertexAttribute &attrib = attribs[attributeIndex];
946         const VertexBinding &binding  = bindings[attrib.bindingIndex];
947         if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
948         {
949             return true;
950         }
951     }
952 
953     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoZeroDivisor);
954     return false;
955 }
956 
ValidTexture3DDestinationTarget(const Context * context,TextureTarget target)957 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
958 {
959     switch (target)
960     {
961         case TextureTarget::_3D:
962             return true;
963         case TextureTarget::_2DArray:
964             return context->getClientVersion() >= Version(3, 0);
965         case TextureTarget::CubeMapArray:
966             return (context->getClientVersion() >= Version(3, 2) ||
967                     context->getExtensions().textureCubeMapArrayAny());
968         default:
969             return false;
970     }
971 }
972 
ValidTexLevelDestinationTarget(const Context * context,TextureType type)973 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
974 {
975     switch (type)
976     {
977         case TextureType::_2D:
978         case TextureType::_2DArray:
979         case TextureType::_2DMultisample:
980         case TextureType::CubeMap:
981         case TextureType::_3D:
982             return true;
983         case TextureType::CubeMapArray:
984             return (context->getClientVersion() >= Version(3, 2) ||
985                     context->getExtensions().textureCubeMapArrayAny());
986         case TextureType::Rectangle:
987             return context->getExtensions().textureRectangleANGLE;
988         case TextureType::_2DMultisampleArray:
989             return context->getExtensions().textureStorageMultisample2dArrayOES;
990         case TextureType::Buffer:
991             return (context->getClientVersion() >= Version(3, 2) ||
992                     context->getExtensions().textureBufferAny());
993         default:
994             return false;
995     }
996 }
997 
ValidFramebufferTarget(const Context * context,GLenum target)998 bool ValidFramebufferTarget(const Context *context, GLenum target)
999 {
1000     static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1001                       GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1002                   "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
1003 
1004     switch (target)
1005     {
1006         case GL_FRAMEBUFFER:
1007             return true;
1008 
1009         case GL_READ_FRAMEBUFFER:
1010         case GL_DRAW_FRAMEBUFFER:
1011             return (context->getExtensions().framebufferBlitAny() ||
1012                     context->getClientMajorVersion() >= 3);
1013 
1014         default:
1015             return false;
1016     }
1017 }
1018 
ValidMipLevel(const Context * context,TextureType type,GLint level)1019 bool ValidMipLevel(const Context *context, TextureType type, GLint level)
1020 {
1021     const auto &caps = context->getCaps();
1022     int maxDimension = 0;
1023     switch (type)
1024     {
1025         case TextureType::_2D:
1026         case TextureType::_2DArray:
1027         case TextureType::_2DMultisample:
1028         case TextureType::_2DMultisampleArray:
1029             // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
1030             // level-of-detail" for multisample textures should be. Could maybe make it zero.
1031             maxDimension = caps.max2DTextureSize;
1032             break;
1033 
1034         case TextureType::CubeMap:
1035         case TextureType::CubeMapArray:
1036             maxDimension = caps.maxCubeMapTextureSize;
1037             break;
1038 
1039         case TextureType::External:
1040         case TextureType::Rectangle:
1041         case TextureType::VideoImage:
1042         case TextureType::Buffer:
1043             return level == 0;
1044 
1045         case TextureType::_3D:
1046             maxDimension = caps.max3DTextureSize;
1047             break;
1048 
1049         default:
1050             UNREACHABLE();
1051     }
1052 
1053     return level <= log2(maxDimension) && level >= 0;
1054 }
1055 
ValidImageSizeParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLint level,GLsizei width,GLsizei height,GLsizei depth,bool isSubImage)1056 bool ValidImageSizeParameters(const Context *context,
1057                               angle::EntryPoint entryPoint,
1058                               TextureType target,
1059                               GLint level,
1060                               GLsizei width,
1061                               GLsizei height,
1062                               GLsizei depth,
1063                               bool isSubImage)
1064 {
1065     if (width < 0 || height < 0 || depth < 0)
1066     {
1067         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
1068         return false;
1069     }
1070     // TexSubImage parameters can be NPOT without textureNPOT extension,
1071     // as long as the destination texture is POT.
1072     bool hasNPOTSupport =
1073         context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0);
1074     if (!isSubImage && !hasNPOTSupport &&
1075         (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
1076     {
1077         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureNotPow2);
1078         return false;
1079     }
1080 
1081     if (!ValidMipLevel(context, target, level))
1082     {
1083         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
1084         return false;
1085     }
1086 
1087     return true;
1088 }
1089 
ValidCompressedBaseLevel(GLsizei size,GLuint blockSize,GLint level)1090 bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level)
1091 {
1092     // Already checked in ValidMipLevel.
1093     ASSERT(level < 32);
1094     // This function is used only for 4x4 BC formats.
1095     ASSERT(blockSize == 4);
1096     // Use the constant value to avoid division.
1097     return ((size << level) % 4) == 0;
1098 }
1099 
ValidCompressedImageSize(const Context * context,GLenum internalFormat,GLint level,GLsizei width,GLsizei height,GLsizei depth)1100 bool ValidCompressedImageSize(const Context *context,
1101                               GLenum internalFormat,
1102                               GLint level,
1103                               GLsizei width,
1104                               GLsizei height,
1105                               GLsizei depth)
1106 {
1107     if (width < 0 || height < 0)
1108     {
1109         return false;
1110     }
1111 
1112     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1113 
1114     if (!formatInfo.compressed && !formatInfo.paletted)
1115     {
1116         return false;
1117     }
1118 
1119     // A texture format can not be both block-compressed and paletted
1120     ASSERT(!(formatInfo.compressed && formatInfo.paletted));
1121 
1122     if (formatInfo.compressed)
1123     {
1124         // Only PVRTC1 requires dimensions to be powers of two
1125         if (IsPVRTC1Format(internalFormat))
1126         {
1127             if (!isPow2(width) || !isPow2(height))
1128             {
1129                 return false;
1130             }
1131 
1132             if (context->getLimitations().squarePvrtc1)
1133             {
1134                 if (width != height)
1135                 {
1136                     return false;
1137                 }
1138             }
1139         }
1140 
1141         if (CompressedTextureFormatRequiresExactSize(internalFormat))
1142         {
1143             // In WebGL compatibility mode and D3D, enforce that the base level implied
1144             // by the compressed texture's mip level would conform to the block
1145             // size.
1146             if (context->isWebGL() ||
1147                 context->getLimitations().compressedBaseMipLevelMultipleOfFour)
1148             {
1149                 // This check is performed only for BC formats.
1150                 ASSERT(formatInfo.compressedBlockDepth == 1);
1151                 if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) ||
1152                     !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level))
1153                 {
1154                     return false;
1155                 }
1156             }
1157             // non-WebGL and non-D3D check is not necessary for the following formats
1158             // From EXT_texture_compression_s3tc specification:
1159             // If the width or height is not a multiple of four, there will be 4x4 blocks at the
1160             // edge of the image that contain "extra" texels that are not part of the image. From
1161             // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an
1162             // RGTC/BPTC image has a width or height that is not a multiple of four, the data
1163             // corresponding to texels outside the image are irrelevant and undefined.
1164         }
1165     }
1166 
1167     if (formatInfo.paletted)
1168     {
1169         // TODO(http://anglebug.com/7688): multi-level paletted images
1170         if (level != 0)
1171         {
1172             return false;
1173         }
1174 
1175         if (!isPow2(width) || !isPow2(height))
1176         {
1177             return false;
1178         }
1179     }
1180 
1181     return true;
1182 }
1183 
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)1184 bool ValidCompressedSubImageSize(const Context *context,
1185                                  GLenum internalFormat,
1186                                  GLint xoffset,
1187                                  GLint yoffset,
1188                                  GLint zoffset,
1189                                  GLsizei width,
1190                                  GLsizei height,
1191                                  GLsizei depth,
1192                                  size_t textureWidth,
1193                                  size_t textureHeight,
1194                                  size_t textureDepth)
1195 {
1196     // Passing non-compressed internal format to sub-image compressed entry points generates
1197     // INVALID_OPERATION, so check it here.
1198     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1199     if (!formatInfo.compressed)
1200     {
1201         return false;
1202     }
1203 
1204     // Negative dimensions already checked in ValidImageSizeParameters called by
1205     // ValidateES2TexImageParametersBase or ValidateES3TexImageParametersBase.
1206     ASSERT(width >= 0 && height >= 0 && depth >= 0);
1207 
1208     // Negative and overflowed offsets already checked in ValidateES2TexImageParametersBase or
1209     // ValidateES3TexImageParametersBase.
1210     ASSERT(xoffset >= 0 && yoffset >= 0 && zoffset >= 0);
1211     ASSERT(std::numeric_limits<GLsizei>::max() - xoffset >= width &&
1212            std::numeric_limits<GLsizei>::max() - yoffset >= height &&
1213            std::numeric_limits<GLsizei>::max() - zoffset >= depth);
1214 
1215     // Ensure that format's block dimensions are set.
1216     ASSERT(formatInfo.compressedBlockWidth > 0 && formatInfo.compressedBlockHeight > 0 &&
1217            formatInfo.compressedBlockDepth > 0);
1218 
1219     // Check if the whole image is being replaced. For 2D texture blocks, zoffset and depth do not
1220     // affect whether the replaced region fills the entire image.
1221     if ((xoffset == 0 && static_cast<size_t>(width) == textureWidth) &&
1222         (yoffset == 0 && static_cast<size_t>(height) == textureHeight) &&
1223         ((zoffset == 0 && static_cast<size_t>(depth) == textureDepth) ||
1224          formatInfo.compressedBlockDepth == 1))
1225     {
1226         // All compressed formats support whole image replacement, early pass.
1227         return true;
1228     }
1229 
1230     // The replaced region does not match the image size. Fail if the format does not support
1231     // partial updates.
1232     if (CompressedFormatRequiresWholeImage(internalFormat))
1233     {
1234         return false;
1235     }
1236 
1237     // The format supports partial updates. Check that the origin of the replaced region is aligned
1238     // to block boundaries.
1239     if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1240         yoffset % formatInfo.compressedBlockHeight != 0 ||
1241         zoffset % formatInfo.compressedBlockDepth != 0)
1242     {
1243         return false;
1244     }
1245 
1246     // The replaced region dimensions must either be multiples of the block dimensions or exactly
1247     // reach the image boundaries.
1248     return (static_cast<size_t>(xoffset + width) == textureWidth ||
1249             width % formatInfo.compressedBlockWidth == 0) &&
1250            (static_cast<size_t>(yoffset + height) == textureHeight ||
1251             height % formatInfo.compressedBlockHeight == 0) &&
1252            (static_cast<size_t>(zoffset + depth) == textureDepth ||
1253             depth % formatInfo.compressedBlockDepth == 0);
1254 }
1255 
ValidImageDataSize(const Context * context,angle::EntryPoint entryPoint,TextureType texType,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels,GLsizei imageSize)1256 bool ValidImageDataSize(const Context *context,
1257                         angle::EntryPoint entryPoint,
1258                         TextureType texType,
1259                         GLsizei width,
1260                         GLsizei height,
1261                         GLsizei depth,
1262                         GLenum format,
1263                         GLenum type,
1264                         const void *pixels,
1265                         GLsizei imageSize)
1266 {
1267     Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
1268     if (pixelUnpackBuffer == nullptr && imageSize < 0)
1269     {
1270         // Checks are not required
1271         return true;
1272     }
1273 
1274     // ...the data would be unpacked from the buffer object such that the memory reads required
1275     // would exceed the data store size.
1276     const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
1277     if (formatInfo.internalFormat == GL_NONE)
1278     {
1279         UNREACHABLE();
1280         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalErrorFormatNotFound);
1281         return false;
1282     }
1283     const Extents size(width, height, depth);
1284     const auto &unpack = context->getState().getUnpackState();
1285 
1286     bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
1287     GLuint endByte  = 0;
1288     if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
1289     {
1290         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
1291         return false;
1292     }
1293 
1294     if (pixelUnpackBuffer)
1295     {
1296         CheckedNumeric<size_t> checkedEndByte(endByte);
1297         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1298         checkedEndByte += checkedOffset;
1299 
1300         if (!checkedEndByte.IsValid() ||
1301             (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1302         {
1303             // Overflow past the end of the buffer
1304             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
1305             return false;
1306         }
1307         if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
1308         {
1309             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1310                                    kPixelUnpackBufferBoundForTransformFeedback);
1311             return false;
1312         }
1313     }
1314     else
1315     {
1316         ASSERT(imageSize >= 0);
1317         if (pixels == nullptr && imageSize != 0)
1318         {
1319             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeMustBeZero);
1320             return false;
1321         }
1322 
1323         if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
1324         {
1325             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeTooSmall);
1326             return false;
1327         }
1328     }
1329 
1330     return true;
1331 }
1332 
ValidQueryType(const Context * context,QueryType queryType)1333 bool ValidQueryType(const Context *context, QueryType queryType)
1334 {
1335     switch (queryType)
1336     {
1337         case QueryType::AnySamples:
1338         case QueryType::AnySamplesConservative:
1339             return context->getClientMajorVersion() >= 3 ||
1340                    context->getExtensions().occlusionQueryBooleanEXT;
1341         case QueryType::TransformFeedbackPrimitivesWritten:
1342             return (context->getClientMajorVersion() >= 3);
1343         case QueryType::TimeElapsed:
1344             return context->getExtensions().disjointTimerQueryEXT;
1345         case QueryType::CommandsCompleted:
1346             return context->getExtensions().syncQueryCHROMIUM;
1347         case QueryType::PrimitivesGenerated:
1348             return context->getClientVersion() >= ES_3_2 ||
1349                    context->getExtensions().geometryShaderAny();
1350         default:
1351             return false;
1352     }
1353 }
1354 
ValidateWebGLVertexAttribPointer(const Context * context,angle::EntryPoint entryPoint,VertexAttribType type,GLboolean normalized,GLsizei stride,const void * ptr,bool pureInteger)1355 bool ValidateWebGLVertexAttribPointer(const Context *context,
1356                                       angle::EntryPoint entryPoint,
1357                                       VertexAttribType type,
1358                                       GLboolean normalized,
1359                                       GLsizei stride,
1360                                       const void *ptr,
1361                                       bool pureInteger)
1362 {
1363     ASSERT(context->isWebGL());
1364     // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1365     // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1366     // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1367     // parameter exceeds 255.
1368     constexpr GLsizei kMaxWebGLStride = 255;
1369     if (stride > kMaxWebGLStride)
1370     {
1371         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
1372         return false;
1373     }
1374 
1375     // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1376     // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1377     // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1378     // or an INVALID_OPERATION error is generated.
1379     angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1380     size_t typeSize              = GetVertexFormatSize(internalType);
1381 
1382     ASSERT(isPow2(typeSize) && typeSize > 0);
1383     size_t sizeMask = (typeSize - 1);
1384     if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1385     {
1386         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
1387         return false;
1388     }
1389 
1390     if ((stride & sizeMask) != 0)
1391     {
1392         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
1393         return false;
1394     }
1395 
1396     return true;
1397 }
1398 
GetValidProgramNoResolve(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1399 Program *GetValidProgramNoResolve(const Context *context,
1400                                   angle::EntryPoint entryPoint,
1401                                   ShaderProgramID id)
1402 {
1403     // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1404     // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1405     // or program object and INVALID_OPERATION if the provided name identifies an object
1406     // that is not the expected type."
1407 
1408     Program *validProgram = context->getProgramNoResolveLink(id);
1409 
1410     if (!validProgram)
1411     {
1412         if (context->getShader(id))
1413         {
1414             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedProgramName);
1415         }
1416         else
1417         {
1418             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
1419         }
1420     }
1421 
1422     return validProgram;
1423 }
1424 
GetValidProgram(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1425 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
1426 {
1427     Program *program = GetValidProgramNoResolve(context, entryPoint, id);
1428     if (program)
1429     {
1430         program->resolveLink(context);
1431     }
1432     return program;
1433 }
1434 
GetValidShader(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1435 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
1436 {
1437     // See ValidProgram for spec details.
1438 
1439     Shader *validShader = context->getShader(id);
1440 
1441     if (!validShader)
1442     {
1443         if (context->getProgramNoResolveLink(id))
1444         {
1445             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedShaderName);
1446         }
1447         else
1448         {
1449             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderName);
1450         }
1451     }
1452 
1453     return validShader;
1454 }
1455 
ValidateAttachmentTarget(const Context * context,angle::EntryPoint entryPoint,GLenum attachment)1456 bool ValidateAttachmentTarget(const Context *context,
1457                               angle::EntryPoint entryPoint,
1458                               GLenum attachment)
1459 {
1460     if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1461     {
1462         if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT)
1463         {
1464             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1465             return false;
1466         }
1467 
1468         // Color attachment 0 is validated below because it is always valid
1469         const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1470         if (colorAttachment >= context->getCaps().maxColorAttachments)
1471         {
1472             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
1473             return false;
1474         }
1475     }
1476     else
1477     {
1478         switch (attachment)
1479         {
1480             case GL_COLOR_ATTACHMENT0:
1481             case GL_DEPTH_ATTACHMENT:
1482             case GL_STENCIL_ATTACHMENT:
1483                 break;
1484 
1485             case GL_DEPTH_STENCIL_ATTACHMENT:
1486                 if (!context->isWebGL() && context->getClientMajorVersion() < 3)
1487                 {
1488                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1489                     return false;
1490                 }
1491                 break;
1492 
1493             default:
1494                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1495                 return false;
1496         }
1497     }
1498 
1499     return true;
1500 }
1501 
ValidateRenderbufferStorageParametersBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1502 bool ValidateRenderbufferStorageParametersBase(const Context *context,
1503                                                angle::EntryPoint entryPoint,
1504                                                GLenum target,
1505                                                GLsizei samples,
1506                                                GLenum internalformat,
1507                                                GLsizei width,
1508                                                GLsizei height)
1509 {
1510     switch (target)
1511     {
1512         case GL_RENDERBUFFER:
1513             break;
1514         default:
1515             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1516             return false;
1517     }
1518 
1519     if (width < 0 || height < 0 || samples < 0)
1520     {
1521         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
1522         return false;
1523     }
1524 
1525     // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1526     GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1527 
1528     const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
1529     if (!formatCaps.renderbuffer)
1530     {
1531         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1532         return false;
1533     }
1534 
1535     // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1536     // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
1537     // only sized internal formats.
1538     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
1539     if (formatInfo.internalFormat == GL_NONE)
1540     {
1541         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1542         return false;
1543     }
1544 
1545     if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
1546     {
1547         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
1548         return false;
1549     }
1550 
1551     RenderbufferID id = context->getState().getRenderbufferId();
1552     if (id.value == 0)
1553     {
1554         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1555         return false;
1556     }
1557 
1558     return true;
1559 }
1560 
ValidateBlitFramebufferParameters(const Context * context,angle::EntryPoint entryPoint,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1561 bool ValidateBlitFramebufferParameters(const Context *context,
1562                                        angle::EntryPoint entryPoint,
1563                                        GLint srcX0,
1564                                        GLint srcY0,
1565                                        GLint srcX1,
1566                                        GLint srcY1,
1567                                        GLint dstX0,
1568                                        GLint dstY0,
1569                                        GLint dstX1,
1570                                        GLint dstY1,
1571                                        GLbitfield mask,
1572                                        GLenum filter)
1573 {
1574     switch (filter)
1575     {
1576         case GL_NEAREST:
1577             break;
1578         case GL_LINEAR:
1579             break;
1580         default:
1581             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kBlitInvalidFilter);
1582             return false;
1583     }
1584 
1585     if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1586     {
1587         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBlitInvalidMask);
1588         return false;
1589     }
1590 
1591     // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1592     // color buffer, leaving only nearest being unfiltered from above
1593     if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1594     {
1595         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
1596         return false;
1597     }
1598 
1599     const auto &glState          = context->getState();
1600     Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1601     Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1602 
1603     if (!readFramebuffer || !drawFramebuffer)
1604     {
1605         ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
1606         return false;
1607     }
1608 
1609     if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
1610     {
1611         return false;
1612     }
1613 
1614     if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer))
1615     {
1616         return false;
1617     }
1618 
1619     // EXT_YUV_target disallows blitting to or from a YUV framebuffer
1620     if ((mask & GL_COLOR_BUFFER_BIT) != 0 &&
1621         (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment()))
1622     {
1623         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitYUVFramebuffer);
1624         return false;
1625     }
1626 
1627     // The draw and read framebuffers can only match if:
1628     // - They are the default framebuffer AND
1629     // - The read/draw surfaces are different
1630     if ((readFramebuffer->id() == drawFramebuffer->id()) &&
1631         ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
1632          (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
1633     {
1634         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitFeedbackLoop);
1635         return false;
1636     }
1637 
1638     // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
1639     // consider it MS. checkReadBufferResourceSamples = false
1640     if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false))
1641     {
1642         return false;
1643     }
1644 
1645     // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1646     // always run it in order to avoid triggering driver bugs.
1647     if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1648         DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1649     {
1650         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
1651         return false;
1652     }
1653 
1654     bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1655 
1656     if (mask & GL_COLOR_BUFFER_BIT)
1657     {
1658         const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
1659         const Extensions &extensions                 = context->getExtensions();
1660 
1661         if (readColorBuffer)
1662         {
1663             const Format &readFormat = readColorBuffer->getFormat();
1664 
1665             for (size_t drawbufferIdx = 0;
1666                  drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
1667             {
1668                 const FramebufferAttachment *attachment =
1669                     drawFramebuffer->getDrawBuffer(drawbufferIdx);
1670                 if (attachment)
1671                 {
1672                     const Format &drawFormat = attachment->getFormat();
1673 
1674                     // The GL ES 3.0.2 spec (pg 193) states that:
1675                     // 1) If the read buffer is fixed point format, the draw buffer must be as well
1676                     // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1677                     // as well
1678                     // 3) If the read buffer is a signed integer format, the draw buffer must be as
1679                     // well
1680                     // Changes with EXT_color_buffer_float:
1681                     // Case 1) is changed to fixed point OR floating point
1682                     GLenum readComponentType = readFormat.info->componentType;
1683                     GLenum drawComponentType = drawFormat.info->componentType;
1684                     bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1685                                            readComponentType == GL_SIGNED_NORMALIZED);
1686                     bool drawFixedPoint      = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1687                                            drawComponentType == GL_SIGNED_NORMALIZED);
1688 
1689                     if (extensions.colorBufferFloatEXT)
1690                     {
1691                         bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1692                         bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1693 
1694                         if (readFixedOrFloat != drawFixedOrFloat)
1695                         {
1696                             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1697                                                    kBlitTypeMismatchFixedOrFloat);
1698                             return false;
1699                         }
1700                     }
1701                     else if (readFixedPoint != drawFixedPoint)
1702                     {
1703                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
1704                         return false;
1705                     }
1706 
1707                     if (readComponentType == GL_UNSIGNED_INT &&
1708                         drawComponentType != GL_UNSIGNED_INT)
1709                     {
1710                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1711                                                kBlitTypeMismatchUnsignedInteger);
1712                         return false;
1713                     }
1714 
1715                     if (readComponentType == GL_INT && drawComponentType != GL_INT)
1716                     {
1717                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1718                                                kBlitTypeMismatchSignedInteger);
1719                         return false;
1720                     }
1721 
1722                     if (readColorBuffer->getResourceSamples() > 0 &&
1723                         (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
1724                     {
1725                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1726                                                kBlitMultisampledFormatOrBoundsMismatch);
1727                         return false;
1728                     }
1729 
1730                     if (context->isWebGL() && *readColorBuffer == *attachment)
1731                     {
1732                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageColor);
1733                         return false;
1734                     }
1735                 }
1736             }
1737 
1738             if (readFormat.info->isInt() && filter == GL_LINEAR)
1739             {
1740                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
1741                 return false;
1742             }
1743         }
1744         // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1745         // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1746         // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1747         // situation is an application error that would lead to a crash in ANGLE.
1748         else if (drawFramebuffer->hasEnabledDrawBuffer())
1749         {
1750             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingColor);
1751             return false;
1752         }
1753     }
1754 
1755     GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1756     GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1757     for (size_t i = 0; i < 2; i++)
1758     {
1759         if (mask & masks[i])
1760         {
1761             const FramebufferAttachment *readBuffer =
1762                 readFramebuffer->getAttachment(context, attachments[i]);
1763             const FramebufferAttachment *drawBuffer =
1764                 drawFramebuffer->getAttachment(context, attachments[i]);
1765 
1766             if (readBuffer && drawBuffer)
1767             {
1768                 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
1769                 {
1770                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitDepthOrStencilFormatMismatch);
1771                     return false;
1772                 }
1773 
1774                 if (readBuffer->getResourceSamples() > 0 && !sameBounds)
1775                 {
1776                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
1777                     return false;
1778                 }
1779 
1780                 if (context->isWebGL() && *readBuffer == *drawBuffer)
1781                 {
1782                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
1783                     return false;
1784                 }
1785             }
1786             // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1787             else if (drawBuffer)
1788             {
1789                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
1790                 return false;
1791             }
1792         }
1793     }
1794 
1795     // OVR_multiview2:
1796     // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1797     // current draw framebuffer isMultiview() or the number of
1798     // views in the current read framebuffer is more than one.
1799     if (readFramebuffer->readDisallowedByMultiview())
1800     {
1801         ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
1802         return false;
1803     }
1804     if (drawFramebuffer->isMultiview())
1805     {
1806         ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
1807         return false;
1808     }
1809 
1810     return true;
1811 }
1812 
ValidateBindFramebufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,FramebufferID framebuffer)1813 bool ValidateBindFramebufferBase(const Context *context,
1814                                  angle::EntryPoint entryPoint,
1815                                  GLenum target,
1816                                  FramebufferID framebuffer)
1817 {
1818     if (!ValidFramebufferTarget(context, target))
1819     {
1820         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1821         return false;
1822     }
1823 
1824     if (!context->getState().isBindGeneratesResourceEnabled() &&
1825         !context->isFramebufferGenerated(framebuffer))
1826     {
1827         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
1828         return false;
1829     }
1830 
1831     return true;
1832 }
1833 
ValidateBindRenderbufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,RenderbufferID renderbuffer)1834 bool ValidateBindRenderbufferBase(const Context *context,
1835                                   angle::EntryPoint entryPoint,
1836                                   GLenum target,
1837                                   RenderbufferID renderbuffer)
1838 {
1839     if (target != GL_RENDERBUFFER)
1840     {
1841         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1842         return false;
1843     }
1844 
1845     if (!context->getState().isBindGeneratesResourceEnabled() &&
1846         !context->isRenderbufferGenerated(renderbuffer))
1847     {
1848         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
1849         return false;
1850     }
1851 
1852     return true;
1853 }
1854 
ValidateFramebufferParameteriBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLint param)1855 bool ValidateFramebufferParameteriBase(const Context *context,
1856                                        angle::EntryPoint entryPoint,
1857                                        GLenum target,
1858                                        GLenum pname,
1859                                        GLint param)
1860 {
1861     if (!ValidFramebufferTarget(context, target))
1862     {
1863         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1864         return false;
1865     }
1866 
1867     switch (pname)
1868     {
1869         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1870         {
1871             GLint maxWidth = context->getCaps().maxFramebufferWidth;
1872             if (param < 0 || param > maxWidth)
1873             {
1874                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferWidth);
1875                 return false;
1876             }
1877             break;
1878         }
1879         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1880         {
1881             GLint maxHeight = context->getCaps().maxFramebufferHeight;
1882             if (param < 0 || param > maxHeight)
1883             {
1884                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferHeight);
1885                 return false;
1886             }
1887             break;
1888         }
1889         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1890         {
1891             GLint maxSamples = context->getCaps().maxFramebufferSamples;
1892             if (param < 0 || param > maxSamples)
1893             {
1894                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferSamples);
1895                 return false;
1896             }
1897             break;
1898         }
1899         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1900         {
1901             break;
1902         }
1903         case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1904         {
1905             if (!context->getExtensions().geometryShaderAny() &&
1906                 context->getClientVersion() < ES_3_2)
1907             {
1908                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
1909                 return false;
1910             }
1911             GLint maxLayers = context->getCaps().maxFramebufferLayers;
1912             if (param < 0 || param > maxLayers)
1913             {
1914                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferLayer);
1915                 return false;
1916             }
1917             break;
1918         }
1919         case GL_FRAMEBUFFER_FLIP_Y_MESA:
1920         {
1921             if (!context->getExtensions().framebufferFlipYMESA)
1922             {
1923                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
1924                 return false;
1925             }
1926             break;
1927         }
1928         default:
1929         {
1930             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
1931             return false;
1932         }
1933     }
1934 
1935     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1936     ASSERT(framebuffer);
1937     if (framebuffer->isDefault())
1938     {
1939         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
1940         return false;
1941     }
1942     return true;
1943 }
1944 
ValidateFramebufferRenderbufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)1945 bool ValidateFramebufferRenderbufferBase(const Context *context,
1946                                          angle::EntryPoint entryPoint,
1947                                          GLenum target,
1948                                          GLenum attachment,
1949                                          GLenum renderbuffertarget,
1950                                          RenderbufferID renderbuffer)
1951 {
1952     if (!ValidFramebufferTarget(context, target))
1953     {
1954         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1955         return false;
1956     }
1957 
1958     if (renderbuffertarget != GL_RENDERBUFFER)
1959     {
1960         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1961         return false;
1962     }
1963 
1964     Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1965 
1966     ASSERT(framebuffer);
1967     if (framebuffer->isDefault())
1968     {
1969         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
1970         return false;
1971     }
1972 
1973     if (!ValidateAttachmentTarget(context, entryPoint, attachment))
1974     {
1975         return false;
1976     }
1977 
1978     // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1979     // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1980     // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1981     // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1982     if (renderbuffer.value != 0)
1983     {
1984         if (!context->getRenderbuffer(renderbuffer))
1985         {
1986             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1987             return false;
1988         }
1989     }
1990 
1991     return true;
1992 }
1993 
ValidateFramebufferTextureBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level)1994 bool ValidateFramebufferTextureBase(const Context *context,
1995                                     angle::EntryPoint entryPoint,
1996                                     GLenum target,
1997                                     GLenum attachment,
1998                                     TextureID texture,
1999                                     GLint level)
2000 {
2001     if (!ValidFramebufferTarget(context, target))
2002     {
2003         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
2004         return false;
2005     }
2006 
2007     if (!ValidateAttachmentTarget(context, entryPoint, attachment))
2008     {
2009         return false;
2010     }
2011 
2012     if (texture.value != 0)
2013     {
2014         Texture *tex = context->getTexture(texture);
2015 
2016         if (tex == nullptr)
2017         {
2018             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
2019             return false;
2020         }
2021 
2022         if (level < 0)
2023         {
2024             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
2025             return false;
2026         }
2027 
2028         // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
2029         // An INVALID_VALUE error is generated if texture is not zero and level is
2030         // not a supported texture level for textarget
2031 
2032         // Common criteria for not supported texture levels(other criteria are handled case by case
2033         // in non base functions): If texture refers to an immutable-format texture, level must be
2034         // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for
2035         // texture.
2036         if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1)
2037         {
2038             if (level >= static_cast<GLint>(tex->getImmutableLevels()))
2039             {
2040                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
2041                 return false;
2042             }
2043         }
2044 
2045         // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
2046         // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture.
2047         if ((context->getClientVersion() >= ES_3_2 ||
2048              context->getExtensions().textureBufferAny()) &&
2049             tex->getType() == TextureType::Buffer)
2050         {
2051             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
2052             return false;
2053         }
2054 
2055         if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent())
2056         {
2057             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
2058                                    "Mismatch between Texture and Context Protected Content state");
2059             return false;
2060         }
2061     }
2062 
2063     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
2064     ASSERT(framebuffer);
2065 
2066     if (framebuffer->isDefault())
2067     {
2068         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
2069         return false;
2070     }
2071 
2072     return true;
2073 }
2074 
ValidateGenerateMipmapBase(const Context * context,angle::EntryPoint entryPoint,TextureType target)2075 bool ValidateGenerateMipmapBase(const Context *context,
2076                                 angle::EntryPoint entryPoint,
2077                                 TextureType target)
2078 {
2079     if (!ValidTextureTarget(context, target))
2080     {
2081         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2082         return false;
2083     }
2084 
2085     Texture *texture = context->getTextureByType(target);
2086 
2087     if (texture == nullptr)
2088     {
2089         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
2090         return false;
2091     }
2092 
2093     const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
2094 
2095     // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
2096     // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
2097     if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2098     {
2099         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelOutOfRange);
2100         return false;
2101     }
2102 
2103     TextureTarget baseTarget = (target == TextureType::CubeMap)
2104                                    ? TextureTarget::CubeMapPositiveX
2105                                    : NonCubeTextureTypeToTarget(target);
2106     const auto &format       = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
2107     if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
2108         format.stencilBits > 0)
2109     {
2110         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2111         return false;
2112     }
2113 
2114     // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
2115     bool formatUnsized = !format.sized;
2116     bool formatColorRenderableAndFilterable =
2117         format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
2118         format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
2119     if (!formatUnsized && !formatColorRenderableAndFilterable)
2120     {
2121         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2122         return false;
2123     }
2124 
2125     // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
2126     // generation
2127     if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
2128     {
2129         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2130         return false;
2131     }
2132 
2133     // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
2134     // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
2135     if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
2136     {
2137         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2138         return false;
2139     }
2140 
2141     // Non-power of 2 ES2 check
2142     if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES &&
2143         (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
2144          !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
2145     {
2146         ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
2147                target == TextureType::CubeMap);
2148         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotPow2);
2149         return false;
2150     }
2151 
2152     // Cube completeness check
2153     if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
2154     {
2155         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCubemapIncomplete);
2156         return false;
2157     }
2158 
2159     if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
2160                                texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
2161     {
2162         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
2163         return false;
2164     }
2165 
2166     return true;
2167 }
2168 
ValidateReadPixelsRobustANGLE(const Context * context,angle::EntryPoint entryPoint,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)2169 bool ValidateReadPixelsRobustANGLE(const Context *context,
2170                                    angle::EntryPoint entryPoint,
2171                                    GLint x,
2172                                    GLint y,
2173                                    GLsizei width,
2174                                    GLsizei height,
2175                                    GLenum format,
2176                                    GLenum type,
2177                                    GLsizei bufSize,
2178                                    const GLsizei *length,
2179                                    const GLsizei *columns,
2180                                    const GLsizei *rows,
2181                                    const void *pixels)
2182 {
2183     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2184     {
2185         return false;
2186     }
2187 
2188     GLsizei writeLength  = 0;
2189     GLsizei writeColumns = 0;
2190     GLsizei writeRows    = 0;
2191 
2192     if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2193                                 &writeLength, &writeColumns, &writeRows, pixels))
2194     {
2195         return false;
2196     }
2197 
2198     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
2199     {
2200         return false;
2201     }
2202 
2203     SetRobustLengthParam(length, writeLength);
2204     SetRobustLengthParam(columns, writeColumns);
2205     SetRobustLengthParam(rows, writeRows);
2206 
2207     return true;
2208 }
2209 
ValidateReadnPixelsEXT(const Context * context,angle::EntryPoint entryPoint,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2210 bool ValidateReadnPixelsEXT(const Context *context,
2211                             angle::EntryPoint entryPoint,
2212                             GLint x,
2213                             GLint y,
2214                             GLsizei width,
2215                             GLsizei height,
2216                             GLenum format,
2217                             GLenum type,
2218                             GLsizei bufSize,
2219                             const void *pixels)
2220 {
2221     if (bufSize < 0)
2222     {
2223         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
2224         return false;
2225     }
2226 
2227     return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2228                                   nullptr, nullptr, nullptr, pixels);
2229 }
2230 
ValidateReadnPixelsRobustANGLE(const Context * context,angle::EntryPoint entryPoint,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)2231 bool ValidateReadnPixelsRobustANGLE(const Context *context,
2232                                     angle::EntryPoint entryPoint,
2233                                     GLint x,
2234                                     GLint y,
2235                                     GLsizei width,
2236                                     GLsizei height,
2237                                     GLenum format,
2238                                     GLenum type,
2239                                     GLsizei bufSize,
2240                                     const GLsizei *length,
2241                                     const GLsizei *columns,
2242                                     const GLsizei *rows,
2243                                     const void *data)
2244 {
2245     GLsizei writeLength  = 0;
2246     GLsizei writeColumns = 0;
2247     GLsizei writeRows    = 0;
2248 
2249     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2250     {
2251         return false;
2252     }
2253 
2254     if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2255                                 &writeLength, &writeColumns, &writeRows, data))
2256     {
2257         return false;
2258     }
2259 
2260     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
2261     {
2262         return false;
2263     }
2264 
2265     SetRobustLengthParam(length, writeLength);
2266     SetRobustLengthParam(columns, writeColumns);
2267     SetRobustLengthParam(rows, writeRows);
2268 
2269     return true;
2270 }
2271 
ValidateGenQueriesEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * ids)2272 bool ValidateGenQueriesEXT(const Context *context,
2273                            angle::EntryPoint entryPoint,
2274                            GLsizei n,
2275                            const QueryID *ids)
2276 {
2277     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2278         !context->getExtensions().disjointTimerQueryEXT)
2279     {
2280         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2281         return false;
2282     }
2283 
2284     return ValidateGenOrDelete(context, entryPoint, n);
2285 }
2286 
ValidateDeleteQueriesEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * ids)2287 bool ValidateDeleteQueriesEXT(const Context *context,
2288                               angle::EntryPoint entryPoint,
2289                               GLsizei n,
2290                               const QueryID *ids)
2291 {
2292     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2293         !context->getExtensions().disjointTimerQueryEXT)
2294     {
2295         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2296         return false;
2297     }
2298 
2299     return ValidateGenOrDelete(context, entryPoint, n);
2300 }
2301 
ValidateIsQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id)2302 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id)
2303 {
2304     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2305         !context->getExtensions().disjointTimerQueryEXT)
2306     {
2307         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2308         return false;
2309     }
2310 
2311     return true;
2312 }
2313 
ValidateBeginQueryBase(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)2314 bool ValidateBeginQueryBase(const Context *context,
2315                             angle::EntryPoint entryPoint,
2316                             QueryType target,
2317                             QueryID id)
2318 {
2319     if (!ValidQueryType(context, target))
2320     {
2321         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2322         return false;
2323     }
2324 
2325     if (id.value == 0)
2326     {
2327         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2328         return false;
2329     }
2330 
2331     // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2332     // of zero, if the active query object name for <target> is non-zero (for the
2333     // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2334     // the active query for either target is non-zero), if <id> is the name of an
2335     // existing query object whose type does not match <target>, or if <id> is the
2336     // active query object name for any query type, the error INVALID_OPERATION is
2337     // generated.
2338 
2339     // Ensure no other queries are active
2340     // NOTE: If other queries than occlusion are supported, we will need to check
2341     // separately that:
2342     //    a) The query ID passed is not the current active query for any target/type
2343     //    b) There are no active queries for the requested target (and in the case
2344     //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2345     //       no query may be active for either if glBeginQuery targets either.
2346 
2347     if (context->getState().isQueryActive(target))
2348     {
2349         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOtherQueryActive);
2350         return false;
2351     }
2352 
2353     // check that name was obtained with glGenQueries
2354     if (!context->isQueryGenerated(id))
2355     {
2356         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2357         return false;
2358     }
2359 
2360     // Check for type mismatch. If query is not yet started we're good to go.
2361     Query *queryObject = context->getQuery(id);
2362     if (queryObject && queryObject->getType() != target)
2363     {
2364         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryTargetMismatch);
2365         return false;
2366     }
2367 
2368     return true;
2369 }
2370 
ValidateBeginQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)2371 bool ValidateBeginQueryEXT(const Context *context,
2372                            angle::EntryPoint entryPoint,
2373                            QueryType target,
2374                            QueryID id)
2375 {
2376     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2377         !context->getExtensions().disjointTimerQueryEXT &&
2378         !context->getExtensions().syncQueryCHROMIUM)
2379     {
2380         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2381         return false;
2382     }
2383 
2384     return ValidateBeginQueryBase(context, entryPoint, target, id);
2385 }
2386 
ValidateEndQueryBase(const Context * context,angle::EntryPoint entryPoint,QueryType target)2387 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target)
2388 {
2389     if (!ValidQueryType(context, target))
2390     {
2391         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2392         return false;
2393     }
2394 
2395     const Query *queryObject = context->getState().getActiveQuery(target);
2396 
2397     if (queryObject == nullptr)
2398     {
2399         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryInactive);
2400         return false;
2401     }
2402 
2403     return true;
2404 }
2405 
ValidateEndQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target)2406 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target)
2407 {
2408     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2409         !context->getExtensions().disjointTimerQueryEXT &&
2410         !context->getExtensions().syncQueryCHROMIUM)
2411     {
2412         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2413         return false;
2414     }
2415 
2416     return ValidateEndQueryBase(context, entryPoint, target);
2417 }
2418 
ValidateQueryCounterEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,QueryType target)2419 bool ValidateQueryCounterEXT(const Context *context,
2420                              angle::EntryPoint entryPoint,
2421                              QueryID id,
2422                              QueryType target)
2423 {
2424     if (!context->getExtensions().disjointTimerQueryEXT)
2425     {
2426         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2427         return false;
2428     }
2429 
2430     if (target != QueryType::Timestamp)
2431     {
2432         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
2433         return false;
2434     }
2435 
2436     if (!context->isQueryGenerated(id))
2437     {
2438         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2439         return false;
2440     }
2441 
2442     // If query object is not started, that's fine.
2443     Query *queryObject = context->getQuery(id);
2444     if (queryObject && context->getState().isQueryActive(queryObject))
2445     {
2446         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
2447         return false;
2448     }
2449 
2450     return true;
2451 }
2452 
ValidateGetQueryivBase(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,GLsizei * numParams)2453 bool ValidateGetQueryivBase(const Context *context,
2454                             angle::EntryPoint entryPoint,
2455                             QueryType target,
2456                             GLenum pname,
2457                             GLsizei *numParams)
2458 {
2459     if (numParams)
2460     {
2461         *numParams = 0;
2462     }
2463 
2464     if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
2465     {
2466         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2467         return false;
2468     }
2469 
2470     switch (pname)
2471     {
2472         case GL_CURRENT_QUERY_EXT:
2473             if (target == QueryType::Timestamp)
2474             {
2475                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
2476                 return false;
2477             }
2478             break;
2479         case GL_QUERY_COUNTER_BITS_EXT:
2480             if (!context->getExtensions().disjointTimerQueryEXT ||
2481                 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
2482             {
2483                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2484                 return false;
2485             }
2486             break;
2487         default:
2488             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2489             return false;
2490     }
2491 
2492     if (numParams)
2493     {
2494         // All queries return only one value
2495         *numParams = 1;
2496     }
2497 
2498     return true;
2499 }
2500 
ValidateGetQueryivEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,const GLint * params)2501 bool ValidateGetQueryivEXT(const Context *context,
2502                            angle::EntryPoint entryPoint,
2503                            QueryType target,
2504                            GLenum pname,
2505                            const GLint *params)
2506 {
2507     if (!context->getExtensions().occlusionQueryBooleanEXT &&
2508         !context->getExtensions().disjointTimerQueryEXT &&
2509         !context->getExtensions().syncQueryCHROMIUM)
2510     {
2511         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2512         return false;
2513     }
2514 
2515     return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
2516 }
2517 
ValidateGetQueryivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)2518 bool ValidateGetQueryivRobustANGLE(const Context *context,
2519                                    angle::EntryPoint entryPoint,
2520                                    QueryType target,
2521                                    GLenum pname,
2522                                    GLsizei bufSize,
2523                                    const GLsizei *length,
2524                                    const GLint *params)
2525 {
2526     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2527     {
2528         return false;
2529     }
2530 
2531     GLsizei numParams = 0;
2532 
2533     if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams))
2534     {
2535         return false;
2536     }
2537 
2538     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2539     {
2540         return false;
2541     }
2542 
2543     SetRobustLengthParam(length, numParams);
2544 
2545     return true;
2546 }
2547 
ValidateGetQueryObjectValueBase(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei * numParams)2548 bool ValidateGetQueryObjectValueBase(const Context *context,
2549                                      angle::EntryPoint entryPoint,
2550                                      QueryID id,
2551                                      GLenum pname,
2552                                      GLsizei *numParams)
2553 {
2554     if (numParams)
2555     {
2556         *numParams = 1;
2557     }
2558 
2559     if (context->isContextLost())
2560     {
2561         ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
2562 
2563         if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
2564         {
2565             // Generate an error but still return true, the context still needs to return a
2566             // value in this case.
2567             return true;
2568         }
2569         else
2570         {
2571             return false;
2572         }
2573     }
2574 
2575     Query *queryObject = context->getQuery(id);
2576 
2577     if (!queryObject)
2578     {
2579         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2580         return false;
2581     }
2582 
2583     if (context->getState().isQueryActive(queryObject))
2584     {
2585         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
2586         return false;
2587     }
2588 
2589     switch (pname)
2590     {
2591         case GL_QUERY_RESULT_EXT:
2592         case GL_QUERY_RESULT_AVAILABLE_EXT:
2593             break;
2594 
2595         default:
2596             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
2597             return false;
2598     }
2599 
2600     return true;
2601 }
2602 
ValidateGetQueryObjectivEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLint * params)2603 bool ValidateGetQueryObjectivEXT(const Context *context,
2604                                  angle::EntryPoint entryPoint,
2605                                  QueryID id,
2606                                  GLenum pname,
2607                                  const GLint *params)
2608 {
2609     if (!context->getExtensions().disjointTimerQueryEXT)
2610     {
2611         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2612         return false;
2613     }
2614     return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2615 }
2616 
ValidateGetQueryObjectivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)2617 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
2618                                          angle::EntryPoint entryPoint,
2619                                          QueryID id,
2620                                          GLenum pname,
2621                                          GLsizei bufSize,
2622                                          const GLsizei *length,
2623                                          const GLint *params)
2624 {
2625     if (!context->getExtensions().disjointTimerQueryEXT)
2626     {
2627         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2628         return false;
2629     }
2630 
2631     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2632     {
2633         return false;
2634     }
2635 
2636     GLsizei numParams = 0;
2637 
2638     if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2639     {
2640         return false;
2641     }
2642 
2643     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2644     {
2645         return false;
2646     }
2647 
2648     SetRobustLengthParam(length, numParams);
2649 
2650     return true;
2651 }
2652 
ValidateGetQueryObjectuivEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLuint * params)2653 bool ValidateGetQueryObjectuivEXT(const Context *context,
2654                                   angle::EntryPoint entryPoint,
2655                                   QueryID id,
2656                                   GLenum pname,
2657                                   const GLuint *params)
2658 {
2659     if (!context->getExtensions().disjointTimerQueryEXT &&
2660         !context->getExtensions().occlusionQueryBooleanEXT &&
2661         !context->getExtensions().syncQueryCHROMIUM)
2662     {
2663         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2664         return false;
2665     }
2666     return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2667 }
2668 
ValidateGetQueryObjectuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)2669 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
2670                                           angle::EntryPoint entryPoint,
2671                                           QueryID id,
2672                                           GLenum pname,
2673                                           GLsizei bufSize,
2674                                           const GLsizei *length,
2675                                           const GLuint *params)
2676 {
2677     if (!context->getExtensions().disjointTimerQueryEXT &&
2678         !context->getExtensions().occlusionQueryBooleanEXT &&
2679         !context->getExtensions().syncQueryCHROMIUM)
2680     {
2681         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2682         return false;
2683     }
2684 
2685     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2686     {
2687         return false;
2688     }
2689 
2690     GLsizei numParams = 0;
2691 
2692     if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2693     {
2694         return false;
2695     }
2696 
2697     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2698     {
2699         return false;
2700     }
2701 
2702     SetRobustLengthParam(length, numParams);
2703 
2704     return true;
2705 }
2706 
ValidateGetQueryObjecti64vEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLint64 * params)2707 bool ValidateGetQueryObjecti64vEXT(const Context *context,
2708                                    angle::EntryPoint entryPoint,
2709                                    QueryID id,
2710                                    GLenum pname,
2711                                    GLint64 *params)
2712 {
2713     if (!context->getExtensions().disjointTimerQueryEXT)
2714     {
2715         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2716         return false;
2717     }
2718     return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2719 }
2720 
ValidateGetQueryObjecti64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * params)2721 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
2722                                            angle::EntryPoint entryPoint,
2723                                            QueryID id,
2724                                            GLenum pname,
2725                                            GLsizei bufSize,
2726                                            const GLsizei *length,
2727                                            GLint64 *params)
2728 {
2729     if (!context->getExtensions().disjointTimerQueryEXT)
2730     {
2731         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2732         return false;
2733     }
2734 
2735     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2736     {
2737         return false;
2738     }
2739 
2740     GLsizei numParams = 0;
2741 
2742     if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2743     {
2744         return false;
2745     }
2746 
2747     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2748     {
2749         return false;
2750     }
2751 
2752     SetRobustLengthParam(length, numParams);
2753 
2754     return true;
2755 }
2756 
ValidateGetQueryObjectui64vEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLuint64 * params)2757 bool ValidateGetQueryObjectui64vEXT(const Context *context,
2758                                     angle::EntryPoint entryPoint,
2759                                     QueryID id,
2760                                     GLenum pname,
2761                                     GLuint64 *params)
2762 {
2763     if (!context->getExtensions().disjointTimerQueryEXT)
2764     {
2765         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2766         return false;
2767     }
2768     return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2769 }
2770 
ValidateGetQueryObjectui64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLuint64 * params)2771 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
2772                                             angle::EntryPoint entryPoint,
2773                                             QueryID id,
2774                                             GLenum pname,
2775                                             GLsizei bufSize,
2776                                             const GLsizei *length,
2777                                             GLuint64 *params)
2778 {
2779     if (!context->getExtensions().disjointTimerQueryEXT)
2780     {
2781         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2782         return false;
2783     }
2784 
2785     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2786     {
2787         return false;
2788     }
2789 
2790     GLsizei numParams = 0;
2791 
2792     if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2793     {
2794         return false;
2795     }
2796 
2797     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2798     {
2799         return false;
2800     }
2801 
2802     SetRobustLengthParam(length, numParams);
2803 
2804     return true;
2805 }
2806 
ValidateUniformCommonBase(const Context * context,angle::EntryPoint entryPoint,const Program * program,UniformLocation location,GLsizei count,const LinkedUniform ** uniformOut)2807 bool ValidateUniformCommonBase(const Context *context,
2808                                angle::EntryPoint entryPoint,
2809                                const Program *program,
2810                                UniformLocation location,
2811                                GLsizei count,
2812                                const LinkedUniform **uniformOut)
2813 {
2814     // TODO(Jiajia): Add image uniform check in future.
2815     if (count < 0)
2816     {
2817         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
2818         return false;
2819     }
2820 
2821     if (!program)
2822     {
2823         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidProgramName);
2824         return false;
2825     }
2826 
2827     if (!program->isLinked())
2828     {
2829         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
2830         return false;
2831     }
2832 
2833     if (location.value == -1)
2834     {
2835         // Silently ignore the uniform command
2836         return false;
2837     }
2838 
2839     const auto &uniformLocations = program->getUniformLocations();
2840     size_t castedLocation        = static_cast<size_t>(location.value);
2841     if (castedLocation >= uniformLocations.size())
2842     {
2843         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
2844         return false;
2845     }
2846 
2847     const auto &uniformLocation = uniformLocations[castedLocation];
2848     if (uniformLocation.ignored)
2849     {
2850         // Silently ignore the uniform command
2851         return false;
2852     }
2853 
2854     if (!uniformLocation.used())
2855     {
2856         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
2857         return false;
2858     }
2859 
2860     const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2861 
2862     // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2863     if (count > 1 && !uniform.isArray())
2864     {
2865         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformCount);
2866         return false;
2867     }
2868 
2869     *uniformOut = &uniform;
2870     return true;
2871 }
2872 
ValidateUniform1ivValue(const Context * context,angle::EntryPoint entryPoint,GLenum uniformType,GLsizei count,const GLint * value)2873 bool ValidateUniform1ivValue(const Context *context,
2874                              angle::EntryPoint entryPoint,
2875                              GLenum uniformType,
2876                              GLsizei count,
2877                              const GLint *value)
2878 {
2879     // Value type is GL_INT, because we only get here from glUniform1i{v}.
2880     // It is compatible with INT or BOOL.
2881     // Do these cheap tests first, for a little extra speed.
2882     if (GL_INT == uniformType || GL_BOOL == uniformType)
2883     {
2884         return true;
2885     }
2886 
2887     if (IsSamplerType(uniformType))
2888     {
2889         // Check that the values are in range.
2890         const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2891         for (GLsizei i = 0; i < count; ++i)
2892         {
2893             if (value[i] < 0 || value[i] >= max)
2894             {
2895                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
2896                 return false;
2897             }
2898         }
2899         return true;
2900     }
2901 
2902     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
2903     return false;
2904 }
2905 
ValidateUniformMatrixValue(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,GLenum uniformType)2906 bool ValidateUniformMatrixValue(const Context *context,
2907                                 angle::EntryPoint entryPoint,
2908                                 GLenum valueType,
2909                                 GLenum uniformType)
2910 {
2911     // Check that the value type is compatible with uniform type.
2912     if (valueType == uniformType)
2913     {
2914         return true;
2915     }
2916 
2917     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
2918     return false;
2919 }
2920 
ValidateUniform(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count)2921 bool ValidateUniform(const Context *context,
2922                      angle::EntryPoint entryPoint,
2923                      GLenum valueType,
2924                      UniformLocation location,
2925                      GLsizei count)
2926 {
2927     const LinkedUniform *uniform = nullptr;
2928     Program *programObject       = context->getActiveLinkedProgram();
2929     return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
2930                                      &uniform) &&
2931            ValidateUniformValue(context, entryPoint, valueType, uniform->getType());
2932 }
2933 
ValidateUniform1iv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLint * value)2934 bool ValidateUniform1iv(const Context *context,
2935                         angle::EntryPoint entryPoint,
2936                         UniformLocation location,
2937                         GLsizei count,
2938                         const GLint *value)
2939 {
2940     const LinkedUniform *uniform = nullptr;
2941     Program *programObject       = context->getActiveLinkedProgram();
2942     return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
2943                                      &uniform) &&
2944            ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value);
2945 }
2946 
ValidateUniformMatrix(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)2947 bool ValidateUniformMatrix(const Context *context,
2948                            angle::EntryPoint entryPoint,
2949                            GLenum valueType,
2950                            UniformLocation location,
2951                            GLsizei count,
2952                            GLboolean transpose)
2953 {
2954     if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
2955     {
2956         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kES3Required);
2957         return false;
2958     }
2959 
2960     const LinkedUniform *uniform = nullptr;
2961     Program *programObject       = context->getActiveLinkedProgram();
2962     return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
2963                                      &uniform) &&
2964            ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType());
2965 }
2966 
ValidateStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLenum * nativeType,unsigned int * numParams)2967 bool ValidateStateQuery(const Context *context,
2968                         angle::EntryPoint entryPoint,
2969                         GLenum pname,
2970                         GLenum *nativeType,
2971                         unsigned int *numParams)
2972 {
2973     if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2974     {
2975         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2976         return false;
2977     }
2978 
2979     const Caps &caps = context->getCaps();
2980 
2981     if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2982     {
2983         int colorAttachment = (pname - GL_DRAW_BUFFER0);
2984 
2985         if (colorAttachment >= caps.maxDrawBuffers)
2986         {
2987             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
2988             return false;
2989         }
2990     }
2991 
2992     switch (pname)
2993     {
2994         case GL_TEXTURE_BINDING_2D:
2995         case GL_TEXTURE_BINDING_CUBE_MAP:
2996         case GL_TEXTURE_BINDING_3D:
2997         case GL_TEXTURE_BINDING_2D_ARRAY:
2998         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
2999             break;
3000         case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
3001             if (!context->getExtensions().textureStorageMultisample2dArrayOES)
3002             {
3003                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
3004                 return false;
3005             }
3006             break;
3007         case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
3008             if (!context->getExtensions().textureRectangleANGLE)
3009             {
3010                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3011                 return false;
3012             }
3013             break;
3014         case GL_TEXTURE_BINDING_EXTERNAL_OES:
3015             if (!context->getExtensions().EGLStreamConsumerExternalNV &&
3016                 !context->getExtensions().EGLImageExternalOES)
3017             {
3018                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3019                 return false;
3020             }
3021             break;
3022         case GL_TEXTURE_BUFFER_BINDING:
3023         case GL_TEXTURE_BINDING_BUFFER:
3024         case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
3025         case GL_MAX_TEXTURE_BUFFER_SIZE:
3026             if (context->getClientVersion() < Version(3, 2) &&
3027                 !context->getExtensions().textureBufferAny())
3028             {
3029                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
3030                 return false;
3031             }
3032             break;
3033 
3034         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3035         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3036         {
3037             Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
3038             ASSERT(readFramebuffer);
3039 
3040             if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint,
3041                                                                    readFramebuffer))
3042             {
3043                 return false;
3044             }
3045 
3046             if (readFramebuffer->getReadBufferState() == GL_NONE)
3047             {
3048                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
3049                 return false;
3050             }
3051 
3052             const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
3053             if (!attachment)
3054             {
3055                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNotAttached);
3056                 return false;
3057             }
3058         }
3059         break;
3060 
3061         case GL_PRIMITIVE_BOUNDING_BOX:
3062             if (!context->getExtensions().primitiveBoundingBoxAny())
3063             {
3064                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
3065                 return false;
3066             }
3067             break;
3068 
3069         case GL_SHADING_RATE_QCOM:
3070             if (!context->getExtensions().shadingRateQCOM)
3071             {
3072                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
3073                 return false;
3074             }
3075             break;
3076 
3077         default:
3078             break;
3079     }
3080 
3081     // pname is valid, but there are no parameters to return
3082     if (*numParams == 0)
3083     {
3084         return false;
3085     }
3086 
3087     return true;
3088 }
3089 
ValidateGetBooleanvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLboolean * params)3090 bool ValidateGetBooleanvRobustANGLE(const Context *context,
3091                                     angle::EntryPoint entryPoint,
3092                                     GLenum pname,
3093                                     GLsizei bufSize,
3094                                     const GLsizei *length,
3095                                     const GLboolean *params)
3096 {
3097     GLenum nativeType;
3098     unsigned int numParams = 0;
3099 
3100     if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3101     {
3102         return false;
3103     }
3104 
3105     SetRobustLengthParam(length, numParams);
3106 
3107     return true;
3108 }
3109 
ValidateGetFloatvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3110 bool ValidateGetFloatvRobustANGLE(const Context *context,
3111                                   angle::EntryPoint entryPoint,
3112                                   GLenum pname,
3113                                   GLsizei bufSize,
3114                                   const GLsizei *length,
3115                                   const GLfloat *params)
3116 {
3117     GLenum nativeType;
3118     unsigned int numParams = 0;
3119 
3120     if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3121     {
3122         return false;
3123     }
3124 
3125     SetRobustLengthParam(length, numParams);
3126 
3127     return true;
3128 }
3129 
ValidateGetIntegervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * data)3130 bool ValidateGetIntegervRobustANGLE(const Context *context,
3131                                     angle::EntryPoint entryPoint,
3132                                     GLenum pname,
3133                                     GLsizei bufSize,
3134                                     const GLsizei *length,
3135                                     const GLint *data)
3136 {
3137     GLenum nativeType;
3138     unsigned int numParams = 0;
3139 
3140     if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3141     {
3142         return false;
3143     }
3144 
3145     SetRobustLengthParam(length, numParams);
3146 
3147     return true;
3148 }
3149 
ValidateGetInteger64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * data)3150 bool ValidateGetInteger64vRobustANGLE(const Context *context,
3151                                       angle::EntryPoint entryPoint,
3152                                       GLenum pname,
3153                                       GLsizei bufSize,
3154                                       const GLsizei *length,
3155                                       GLint64 *data)
3156 {
3157     GLenum nativeType;
3158     unsigned int numParams = 0;
3159 
3160     if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3161     {
3162         return false;
3163     }
3164 
3165     if (nativeType == GL_INT_64_ANGLEX)
3166     {
3167         CastStateValues(context, nativeType, pname, numParams, data);
3168         return false;
3169     }
3170 
3171     SetRobustLengthParam(length, numParams);
3172     return true;
3173 }
3174 
ValidateRobustStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,GLenum * nativeType,unsigned int * numParams)3175 bool ValidateRobustStateQuery(const Context *context,
3176                               angle::EntryPoint entryPoint,
3177                               GLenum pname,
3178                               GLsizei bufSize,
3179                               GLenum *nativeType,
3180                               unsigned int *numParams)
3181 {
3182     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3183     {
3184         return false;
3185     }
3186 
3187     if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams))
3188     {
3189         return false;
3190     }
3191 
3192     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams))
3193     {
3194         return false;
3195     }
3196 
3197     return true;
3198 }
3199 
ValidateCopyImageSubDataTarget(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target)3200 bool ValidateCopyImageSubDataTarget(const Context *context,
3201                                     angle::EntryPoint entryPoint,
3202                                     GLuint name,
3203                                     GLenum target)
3204 {
3205     // From EXT_copy_image: INVALID_ENUM is generated if either <srcTarget> or <dstTarget> is not
3206     // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the
3207     // cubemap face selectors described in table 3.17, or if the target does not match the type of
3208     // the object. INVALID_VALUE is generated if either <srcName> or <dstName> does not correspond
3209     // to a valid renderbuffer or texture object according to the corresponding target parameter.
3210     switch (target)
3211     {
3212         case GL_RENDERBUFFER:
3213         {
3214             RenderbufferID renderbuffer = PackParam<RenderbufferID>(name);
3215             if (!context->isRenderbuffer(renderbuffer))
3216             {
3217                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName);
3218                 return false;
3219             }
3220             break;
3221         }
3222         case GL_TEXTURE_2D:
3223         case GL_TEXTURE_3D:
3224         case GL_TEXTURE_2D_ARRAY:
3225         case GL_TEXTURE_CUBE_MAP:
3226         case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3227         {
3228             TextureID texture = PackParam<TextureID>(name);
3229             if (!context->isTexture(texture))
3230             {
3231                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName);
3232                 return false;
3233             }
3234 
3235             Texture *textureObject = context->getTexture(texture);
3236             if (textureObject && textureObject->getType() != PackParam<TextureType>(target))
3237             {
3238                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTextureTypeMismatch);
3239                 return false;
3240             }
3241             break;
3242         }
3243         default:
3244             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3245             return false;
3246     }
3247 
3248     return true;
3249 }
3250 
ValidateCopyImageSubDataLevel(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLint level)3251 bool ValidateCopyImageSubDataLevel(const Context *context,
3252                                    angle::EntryPoint entryPoint,
3253                                    GLenum target,
3254                                    GLint level)
3255 {
3256     switch (target)
3257     {
3258         case GL_RENDERBUFFER:
3259         {
3260             if (level != 0)
3261             {
3262                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3263                 return false;
3264             }
3265             break;
3266         }
3267         case GL_TEXTURE_2D:
3268         case GL_TEXTURE_3D:
3269         case GL_TEXTURE_2D_ARRAY:
3270         case GL_TEXTURE_CUBE_MAP:
3271         case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3272         {
3273             if (!ValidMipLevel(context, PackParam<TextureType>(target), level))
3274             {
3275                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3276                 return false;
3277             }
3278             break;
3279         }
3280         default:
3281             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3282             return false;
3283     }
3284 
3285     return true;
3286 }
3287 
ValidateCopyImageSubDataTargetRegion(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target,GLint level,GLint offsetX,GLint offsetY,GLint offsetZ,GLsizei width,GLsizei height,GLsizei * samples)3288 bool ValidateCopyImageSubDataTargetRegion(const Context *context,
3289                                           angle::EntryPoint entryPoint,
3290                                           GLuint name,
3291                                           GLenum target,
3292                                           GLint level,
3293                                           GLint offsetX,
3294                                           GLint offsetY,
3295                                           GLint offsetZ,
3296                                           GLsizei width,
3297                                           GLsizei height,
3298                                           GLsizei *samples)
3299 {
3300     // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
3301     // of the corresponding image object.
3302     if (offsetX < 0 || offsetY < 0 || offsetZ < 0)
3303     {
3304         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3305         return false;
3306     }
3307 
3308     if (target == GL_RENDERBUFFER)
3309     {
3310         // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
3311         // boundaries of the corresponding image object
3312         Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
3313         if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height))
3314         {
3315             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
3316             return false;
3317         }
3318     }
3319     else
3320     {
3321         Texture *texture = context->getTexture(PackParam<TextureID>(name));
3322 
3323         // INVALID_OPERATION is generated if either object is a texture and the texture is not
3324         // complete
3325         // This will handle the texture completeness check. Note that this ignores format-based
3326         // compleness rules.
3327         if (!texture->isSamplerCompleteForCopyImage(context, nullptr))
3328         {
3329             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNotTextureComplete);
3330             return false;
3331         }
3332 
3333         GLenum textureTargetToUse = target;
3334         if (target == GL_TEXTURE_CUBE_MAP)
3335         {
3336             // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
3337             textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3338         }
3339 
3340         const GLsizei textureWidth = static_cast<GLsizei>(
3341             texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level));
3342         const GLsizei textureHeight = static_cast<GLsizei>(
3343             texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level));
3344 
3345         // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
3346         // boundaries of the corresponding image object
3347         if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height))
3348         {
3349             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
3350             return false;
3351         }
3352 
3353         *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level);
3354         *samples = (*samples == 0) ? 1 : *samples;
3355     }
3356 
3357     return true;
3358 }
3359 
ValidateCompressedRegion(const Context * context,angle::EntryPoint entryPoint,const InternalFormat & formatInfo,GLsizei width,GLsizei height)3360 bool ValidateCompressedRegion(const Context *context,
3361                               angle::EntryPoint entryPoint,
3362                               const InternalFormat &formatInfo,
3363                               GLsizei width,
3364                               GLsizei height)
3365 {
3366     ASSERT(formatInfo.compressed);
3367 
3368     // INVALID_VALUE is generated if the image format is compressed and the dimensions of the
3369     // subregion fail to meet the alignment constraints of the format.
3370     if ((width % formatInfo.compressedBlockWidth != 0) ||
3371         (height % formatInfo.compressedBlockHeight != 0))
3372     {
3373         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedRegionSize);
3374         return false;
3375     }
3376 
3377     return true;
3378 }
3379 
GetTargetFormatInfo(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target,GLint level)3380 const InternalFormat &GetTargetFormatInfo(const Context *context,
3381                                           angle::EntryPoint entryPoint,
3382                                           GLuint name,
3383                                           GLenum target,
3384                                           GLint level)
3385 {
3386     static const InternalFormat defaultInternalFormat;
3387 
3388     switch (target)
3389     {
3390         case GL_RENDERBUFFER:
3391         {
3392             Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
3393             return *buffer->getFormat().info;
3394         }
3395         case GL_TEXTURE_2D:
3396         case GL_TEXTURE_3D:
3397         case GL_TEXTURE_2D_ARRAY:
3398         case GL_TEXTURE_CUBE_MAP:
3399         case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3400         {
3401             Texture *texture          = context->getTexture(PackParam<TextureID>(name));
3402             GLenum textureTargetToUse = target;
3403 
3404             if (target == GL_TEXTURE_CUBE_MAP)
3405             {
3406                 // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the
3407                 // textureWidth/textureHeight
3408                 textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3409             }
3410             return *texture->getFormat(PackParam<TextureTarget>(textureTargetToUse), level).info;
3411         }
3412         default:
3413             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3414             return defaultInternalFormat;
3415     }
3416 }
3417 
ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat,GLenum compressedFormat)3418 bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat)
3419 {
3420     // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the
3421     // EXT_copy_image spec.
3422     switch (compressedFormat)
3423     {
3424         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
3425         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
3426         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
3427         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
3428         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
3429         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
3430         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
3431         case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
3432         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
3433         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
3434         case GL_COMPRESSED_RGBA8_ETC2_EAC:
3435         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
3436         case GL_COMPRESSED_RG11_EAC:
3437         case GL_COMPRESSED_SIGNED_RG11_EAC:
3438         case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
3439         case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
3440         case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
3441         case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
3442         case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
3443         case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
3444         case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
3445         case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
3446         case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
3447         case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
3448         case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
3449         case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
3450         case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
3451         case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
3452         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
3453         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
3454         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
3455         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
3456         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
3457         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
3458         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
3459         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
3460         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
3461         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
3462         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
3463         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
3464         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
3465         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
3466         case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
3467         case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
3468         case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
3469         case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
3470         case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
3471         case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
3472         case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
3473         case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
3474         case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
3475         case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
3476         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
3477         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
3478         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
3479         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
3480         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
3481         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
3482         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
3483         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
3484         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
3485         case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
3486         {
3487             switch (uncompressedFormat)
3488             {
3489                 case GL_RGBA32UI:
3490                 case GL_RGBA32I:
3491                 case GL_RGBA32F:
3492                     return true;
3493                 default:
3494                     return false;
3495             }
3496         }
3497         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
3498         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
3499         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
3500         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
3501         case GL_COMPRESSED_RED_RGTC1_EXT:
3502         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
3503         case GL_COMPRESSED_RGB8_ETC2:
3504         case GL_COMPRESSED_SRGB8_ETC2:
3505         case GL_COMPRESSED_R11_EAC:
3506         case GL_COMPRESSED_SIGNED_R11_EAC:
3507         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3508         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3509         {
3510             switch (uncompressedFormat)
3511             {
3512                 case GL_RGBA16UI:
3513                 case GL_RGBA16I:
3514                 case GL_RGBA16F:
3515                 case GL_RG32UI:
3516                 case GL_RG32I:
3517                 case GL_RG32F:
3518                     return true;
3519                 default:
3520                     return false;
3521             }
3522         }
3523         default:
3524             break;
3525     }
3526 
3527     return false;
3528 }
3529 
ValidateCopyCompressedFormatCompatible(const InternalFormat & srcFormatInfo,const InternalFormat & dstFormatInfo)3530 bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo,
3531                                             const InternalFormat &dstFormatInfo)
3532 {
3533     // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec.
3534 
3535     ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat);
3536 
3537     const GLenum srcFormat = srcFormatInfo.internalFormat;
3538     const GLenum dstFormat = dstFormatInfo.internalFormat;
3539 
3540     switch (srcFormat)
3541     {
3542         case GL_COMPRESSED_RED_RGTC1_EXT:
3543             return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT);
3544         case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
3545             return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT);
3546         case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
3547             return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
3548         case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
3549             return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT);
3550         case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
3551             return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
3552         case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
3553             return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
3554         case GL_COMPRESSED_R11_EAC:
3555             return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC);
3556         case GL_COMPRESSED_SIGNED_R11_EAC:
3557             return (dstFormat == GL_COMPRESSED_R11_EAC);
3558         case GL_COMPRESSED_RG11_EAC:
3559             return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC);
3560         case GL_COMPRESSED_SIGNED_RG11_EAC:
3561             return (dstFormat == GL_COMPRESSED_RG11_EAC);
3562         default:
3563             break;
3564     }
3565 
3566     // Since they can't be the same format and are both compressed formats, one must be linear and
3567     // the other nonlinear.
3568     if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding)
3569     {
3570         return false;
3571     }
3572 
3573     const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat;
3574     const GLenum nonLinearFormat =
3575         (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat;
3576 
3577     switch (linearFormat)
3578     {
3579         case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
3580             return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
3581         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
3582             return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
3583         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
3584             return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
3585         case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
3586             return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
3587         case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
3588             return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
3589         case GL_COMPRESSED_RGB8_ETC2:
3590             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2);
3591         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3592             return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
3593         case GL_COMPRESSED_RGBA8_ETC2_EAC:
3594             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
3595         case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
3596             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
3597         case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
3598             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
3599         case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
3600             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
3601         case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
3602             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
3603         case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
3604             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
3605         case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
3606             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
3607         case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
3608             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
3609         case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
3610             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
3611         case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
3612             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
3613         case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
3614             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
3615         case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
3616             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
3617         case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
3618             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
3619         case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
3620             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
3621         case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
3622             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
3623         case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
3624             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES);
3625         case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
3626             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES);
3627         case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
3628             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES);
3629         case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
3630             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES);
3631         case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
3632             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES);
3633         case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
3634             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES);
3635         case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
3636             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES);
3637         case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
3638             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES);
3639         case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
3640             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES);
3641         case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
3642             return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES);
3643         default:
3644             break;
3645     }
3646 
3647     return false;
3648 }
3649 
ValidateCopyFormatCompatible(const InternalFormat & srcFormatInfo,const InternalFormat & dstFormatInfo)3650 bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo,
3651                                   const InternalFormat &dstFormatInfo)
3652 {
3653     // Matching source and destination formats are compatible.
3654     if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat)
3655     {
3656         return true;
3657     }
3658 
3659     if (srcFormatInfo.compressed != dstFormatInfo.compressed)
3660     {
3661         GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
3662                                                                 : dstFormatInfo.internalFormat;
3663         GLenum compressedFormat   = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
3664                                                                : dstFormatInfo.internalFormat;
3665 
3666         return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat);
3667     }
3668 
3669     if (!srcFormatInfo.compressed)
3670     {
3671         // Source and destination are uncompressed formats.
3672         return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes);
3673     }
3674 
3675     return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo);
3676 }
3677 
ValidateCopyImageSubDataBase(const Context * context,angle::EntryPoint entryPoint,GLuint srcName,GLenum srcTarget,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLuint dstName,GLenum dstTarget,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)3678 bool ValidateCopyImageSubDataBase(const Context *context,
3679                                   angle::EntryPoint entryPoint,
3680                                   GLuint srcName,
3681                                   GLenum srcTarget,
3682                                   GLint srcLevel,
3683                                   GLint srcX,
3684                                   GLint srcY,
3685                                   GLint srcZ,
3686                                   GLuint dstName,
3687                                   GLenum dstTarget,
3688                                   GLint dstLevel,
3689                                   GLint dstX,
3690                                   GLint dstY,
3691                                   GLint dstZ,
3692                                   GLsizei srcWidth,
3693                                   GLsizei srcHeight,
3694                                   GLsizei srcDepth)
3695 {
3696     // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
3697     // of the corresponding image object
3698     if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0))
3699     {
3700         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3701         return false;
3702     }
3703 
3704     if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget))
3705     {
3706         return false;
3707     }
3708     if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget))
3709     {
3710         return false;
3711     }
3712 
3713     if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel))
3714     {
3715         return false;
3716     }
3717     if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel))
3718     {
3719         return false;
3720     }
3721 
3722     const InternalFormat &srcFormatInfo =
3723         GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel);
3724     const InternalFormat &dstFormatInfo =
3725         GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel);
3726     GLsizei dstWidth   = srcWidth;
3727     GLsizei dstHeight  = srcHeight;
3728     GLsizei srcSamples = 1;
3729     GLsizei dstSamples = 1;
3730 
3731     if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE)
3732     {
3733         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureLevel);
3734         return false;
3735     }
3736 
3737     if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel,
3738                                               srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples))
3739     {
3740         return false;
3741     }
3742 
3743     // When copying from a compressed image to an uncompressed image the image texel dimensions
3744     // written to the uncompressed image will be source extent divided by the compressed texel block
3745     // dimensions.
3746     if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed))
3747     {
3748         ASSERT(srcFormatInfo.compressedBlockWidth != 0);
3749         ASSERT(srcFormatInfo.compressedBlockHeight != 0);
3750 
3751         dstWidth /= srcFormatInfo.compressedBlockWidth;
3752         dstHeight /= srcFormatInfo.compressedBlockHeight;
3753     }
3754     // When copying from an uncompressed image to a compressed image the image texel dimensions
3755     // written to the compressed image will be the source extent multiplied by the compressed texel
3756     // block dimensions.
3757     else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed))
3758     {
3759         dstWidth *= dstFormatInfo.compressedBlockWidth;
3760         dstHeight *= dstFormatInfo.compressedBlockHeight;
3761     }
3762 
3763     if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel,
3764                                               dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples))
3765     {
3766         return false;
3767     }
3768 
3769     bool fillsEntireMip               = false;
3770     gl::Texture *dstTexture           = context->getTexture({dstName});
3771     gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget);
3772     // TODO(http://anglebug.com/5643): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) are
3773     // unsupported when used with compressed formats due to gl::PackParam() returning
3774     // TextureTarget::InvalidEnum.
3775     if (dstTargetPacked != gl::TextureTarget::InvalidEnum)
3776     {
3777         const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel);
3778         fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width &&
3779                          srcHeight == dstExtents.height && srcDepth == dstExtents.depth;
3780     }
3781 
3782     if (srcFormatInfo.compressed && !fillsEntireMip &&
3783         !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight))
3784     {
3785         return false;
3786     }
3787 
3788     if (dstFormatInfo.compressed && !fillsEntireMip &&
3789         !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight))
3790     {
3791         return false;
3792     }
3793 
3794     // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats
3795     // are not compatible, if one image is compressed and the other is uncompressed and the block
3796     // size of compressed image is not equal to the texel size of the compressed image.
3797     if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo))
3798     {
3799         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIncompatibleTextures);
3800         return false;
3801     }
3802 
3803     // INVALID_OPERATION is generated if the source and destination number of samples do not match
3804     if (srcSamples != dstSamples)
3805     {
3806         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3807         return false;
3808     }
3809 
3810     return true;
3811 }
3812 
ValidateCopyTexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border,Format * textureFormatOut)3813 bool ValidateCopyTexImageParametersBase(const Context *context,
3814                                         angle::EntryPoint entryPoint,
3815                                         TextureTarget target,
3816                                         GLint level,
3817                                         GLenum internalformat,
3818                                         bool isSubImage,
3819                                         GLint xoffset,
3820                                         GLint yoffset,
3821                                         GLint zoffset,
3822                                         GLint x,
3823                                         GLint y,
3824                                         GLsizei width,
3825                                         GLsizei height,
3826                                         GLint border,
3827                                         Format *textureFormatOut)
3828 {
3829     TextureType texType = TextureTargetToType(target);
3830 
3831     if (xoffset < 0 || yoffset < 0 || zoffset < 0)
3832     {
3833         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3834         return false;
3835     }
3836 
3837     if (width < 0 || height < 0)
3838     {
3839         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3840         return false;
3841     }
3842 
3843     if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3844         std::numeric_limits<GLsizei>::max() - yoffset < height)
3845     {
3846         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
3847         return false;
3848     }
3849 
3850     if (std::numeric_limits<GLint>::max() - width < x ||
3851         std::numeric_limits<GLint>::max() - height < y)
3852     {
3853         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3854         return false;
3855     }
3856 
3857     if (border != 0)
3858     {
3859         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
3860         return false;
3861     }
3862 
3863     if (!ValidMipLevel(context, texType, level))
3864     {
3865         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3866         return false;
3867     }
3868 
3869     const State &state           = context->getState();
3870     Framebuffer *readFramebuffer = state.getReadFramebuffer();
3871     if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
3872     {
3873         return false;
3874     }
3875 
3876     // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since
3877     // they will be resolved before copying.
3878     if (!readFramebuffer->isDefault() &&
3879         !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
3880     {
3881         return false;
3882     }
3883 
3884     if (readFramebuffer->getReadBufferState() == GL_NONE)
3885     {
3886         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
3887         return false;
3888     }
3889 
3890     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3891     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
3892     // attachment and WebGL defines it to be an error. We do the check unconditionally as the
3893     // situation is an application error that would lead to a crash in ANGLE.
3894     const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
3895     if (source == nullptr)
3896     {
3897         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
3898         return false;
3899     }
3900 
3901     if (source->isYUV())
3902     {
3903         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCopyFromYUVFramebuffer);
3904         return false;
3905     }
3906 
3907     // OVR_multiview spec:
3908     // INVALID_FRAMEBUFFER_OPERATION is generated by commands that read from the
3909     // framebuffer such as BlitFramebuffer, ReadPixels, CopyTexImage*, and
3910     // CopyTexSubImage*, if the number of views in the current read framebuffer
3911     // is greater than 1.
3912     if (readFramebuffer->readDisallowedByMultiview())
3913     {
3914         ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
3915         return false;
3916     }
3917 
3918     const Caps &caps = context->getCaps();
3919 
3920     GLint maxDimension = 0;
3921     switch (texType)
3922     {
3923         case TextureType::_2D:
3924             maxDimension = caps.max2DTextureSize;
3925             break;
3926 
3927         case TextureType::CubeMap:
3928         case TextureType::CubeMapArray:
3929             maxDimension = caps.maxCubeMapTextureSize;
3930             break;
3931 
3932         case TextureType::Rectangle:
3933             maxDimension = caps.maxRectangleTextureSize;
3934             break;
3935 
3936         case TextureType::_2DArray:
3937             maxDimension = caps.max2DTextureSize;
3938             break;
3939 
3940         case TextureType::_3D:
3941             maxDimension = caps.max3DTextureSize;
3942             break;
3943 
3944         default:
3945             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
3946             return false;
3947     }
3948 
3949     Texture *texture = state.getTargetTexture(texType);
3950     if (!texture)
3951     {
3952         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
3953         return false;
3954     }
3955 
3956     if (texture->getImmutableFormat() && !isSubImage)
3957     {
3958         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
3959         return false;
3960     }
3961 
3962     const InternalFormat &formatInfo =
3963         isSubImage ? *texture->getFormat(target, level).info
3964                    : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
3965 
3966     if (formatInfo.depthBits > 0 || formatInfo.compressed)
3967     {
3968         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
3969         return false;
3970     }
3971 
3972     if (isSubImage)
3973     {
3974         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3975             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3976             static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
3977         {
3978             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
3979             return false;
3980         }
3981     }
3982     else
3983     {
3984         if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
3985             width != height)
3986         {
3987             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapIncomplete);
3988             return false;
3989         }
3990 
3991         if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
3992         {
3993             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
3994             return false;
3995         }
3996 
3997         int maxLevelDimension = (maxDimension >> level);
3998         if (static_cast<int>(width) > maxLevelDimension ||
3999             static_cast<int>(height) > maxLevelDimension)
4000         {
4001             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
4002             return false;
4003         }
4004     }
4005 
4006     // Do not leak the previous texture format for non-subImage case.
4007     if (textureFormatOut && isSubImage)
4008     {
4009         *textureFormatOut = texture->getFormat(target, level);
4010     }
4011 
4012     // Detect texture copying feedback loops for WebGL.
4013     if (context->isWebGL())
4014     {
4015         if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
4016         {
4017             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFeedbackLoop);
4018             return false;
4019         }
4020     }
4021 
4022     return true;
4023 }
4024 
ValidateProgramPipelineDrawStates(const Context * context,const Extensions & extensions,ProgramPipeline * programPipeline)4025 const char *ValidateProgramPipelineDrawStates(const Context *context,
4026                                               const Extensions &extensions,
4027                                               ProgramPipeline *programPipeline)
4028 {
4029     for (const ShaderType shaderType : gl::AllShaderTypes())
4030     {
4031         Program *program = programPipeline->getShaderProgram(shaderType);
4032         if (program)
4033         {
4034             const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
4035             if (errorMsg)
4036             {
4037                 return errorMsg;
4038             }
4039         }
4040     }
4041 
4042     return nullptr;
4043 }
4044 
ValidateProgramPipelineAttachedPrograms(ProgramPipeline * programPipeline)4045 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
4046 {
4047     // An INVALID_OPERATION error is generated by any command that transfers vertices to the
4048     // GL or launches compute work if the current set of active
4049     // program objects cannot be executed, for reasons including:
4050     // - There is no current program object specified by UseProgram, there is a current program
4051     //    pipeline object, and that object is empty (no executable code is installed for any stage).
4052     // - A program object is active for at least one, but not all of the shader
4053     // stages that were present when the program was linked.
4054     if (!programPipeline->getExecutable().getLinkedShaderStages().any())
4055     {
4056         return gl::err::kNoExecutableCodeInstalled;
4057     }
4058     for (const ShaderType shaderType : gl::AllShaderTypes())
4059     {
4060         Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
4061         if (shaderProgram)
4062         {
4063             ProgramExecutable &executable = shaderProgram->getExecutable();
4064             for (const ShaderType programShaderType : executable.getLinkedShaderStages())
4065             {
4066                 if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
4067                 {
4068                     return gl::err::kNotAllStagesOfSeparableProgramUsed;
4069                 }
4070             }
4071         }
4072     }
4073 
4074     // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders
4075     // A non-separable program object or program pipeline object that includes
4076     // a geometry shader must also include a vertex shader.
4077     // An INVALID_OPERATION error is generated by any command that transfers
4078     // vertices to the GL if the current program state has a geometry shader
4079     // but no vertex shader.
4080     if (!programPipeline->getShaderProgram(ShaderType::Vertex) &&
4081         programPipeline->getShaderProgram(ShaderType::Geometry))
4082     {
4083         return gl::err::kNoActiveGraphicsShaderStage;
4084     }
4085 
4086     return nullptr;
4087 }
4088 
ValidateDrawStates(const Context * context,GLenum * outErrorCode)4089 const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode)
4090 {
4091     // Note all errors returned from this function are INVALID_OPERATION except for the draw
4092     // framebuffer completeness check.
4093     *outErrorCode = GL_INVALID_OPERATION;
4094 
4095     const Extensions &extensions = context->getExtensions();
4096     const State &state           = context->getState();
4097 
4098     // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
4099     // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
4100     // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
4101     VertexArray *vertexArray = state.getVertexArray();
4102     ASSERT(vertexArray);
4103 
4104     if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer())
4105     {
4106         return kBufferMapped;
4107     }
4108 
4109     // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
4110     // Section 6.10 of the WebGL 1.0 spec.
4111     Framebuffer *framebuffer = state.getDrawFramebuffer();
4112     ASSERT(framebuffer);
4113 
4114     if (context->getLimitations().noSeparateStencilRefsAndMasks ||
4115         extensions.webglCompatibilityANGLE)
4116     {
4117         ASSERT(framebuffer);
4118         const FramebufferAttachment *dsAttachment =
4119             framebuffer->getStencilOrDepthStencilAttachment();
4120         const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
4121         ASSERT(stencilBits <= 8);
4122 
4123         const DepthStencilState &depthStencilState = state.getDepthStencilState();
4124         if (depthStencilState.stencilTest && stencilBits > 0)
4125         {
4126             GLuint maxStencilValue = (1 << stencilBits) - 1;
4127 
4128             bool differentRefs =
4129                 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
4130                 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
4131             bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
4132                                        (depthStencilState.stencilBackWritemask & maxStencilValue);
4133             bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
4134                                   (depthStencilState.stencilBackMask & maxStencilValue);
4135 
4136             if (differentRefs || differentWritemasks || differentMasks)
4137             {
4138                 if (!extensions.webglCompatibilityANGLE)
4139                 {
4140                     WARN() << "This ANGLE implementation does not support separate front/back "
4141                               "stencil writemasks, reference values, or stencil mask values.";
4142                 }
4143                 return kStencilReferenceMaskOrMismatch;
4144             }
4145         }
4146     }
4147 
4148     if (!extensions.floatBlendEXT)
4149     {
4150         const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
4151             state.getBlendEnabledDrawBufferMask() &
4152             framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
4153         if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
4154         {
4155             return kUnsupportedFloatBlending;
4156         }
4157     }
4158 
4159     if (extensions.renderSharedExponentQCOM)
4160     {
4161         if (!ValidateColorMasksForSharedExponentColorBuffers(state.getBlendStateExt(), framebuffer))
4162         {
4163             return kUnsupportedColorMaskForSharedExponentColorBuffer;
4164         }
4165     }
4166 
4167     if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4168         extensions.webglCompatibilityANGLE)
4169     {
4170         if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
4171         {
4172             if (extensions.webglCompatibilityANGLE)
4173             {
4174                 return kInvalidConstantColor;
4175             }
4176 
4177             WARN() << kConstantColorAlphaLimitation;
4178             return kConstantColorAlphaLimitation;
4179         }
4180     }
4181 
4182     const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
4183     if (!framebufferStatus.isComplete())
4184     {
4185         *outErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION;
4186         ASSERT(framebufferStatus.reason);
4187         return framebufferStatus.reason;
4188     }
4189 
4190     bool framebufferIsYUV = framebuffer->hasYUVAttachment();
4191     if (framebufferIsYUV)
4192     {
4193         const BlendState &blendState = state.getBlendState();
4194         if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue)
4195         {
4196             // When rendering into a YUV framebuffer, the color mask must have r g and b set to
4197             // true.
4198             return kInvalidColorMaskForYUV;
4199         }
4200 
4201         if (blendState.blend)
4202         {
4203             // When rendering into a YUV framebuffer, blending must be disabled.
4204             return kInvalidBlendStateForYUV;
4205         }
4206     }
4207     else
4208     {
4209         if (framebuffer->hasExternalTextureAttachment())
4210         {
4211             // It is an error to render into an external texture that is not YUV.
4212             return kExternalTextureAttachmentNotYUV;
4213         }
4214     }
4215 
4216     // Advanced blend equation can only be enabled for a single render target.
4217     const BlendStateExt &blendStateExt = state.getBlendStateExt();
4218     if (blendStateExt.getUsesAdvancedBlendEquationMask().any())
4219     {
4220         const size_t drawBufferCount            = framebuffer->getDrawbufferStateCount();
4221         uint32_t advancedBlendRenderTargetCount = 0;
4222 
4223         for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask())
4224         {
4225             if (drawBufferIndex < drawBufferCount &&
4226                 framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE &&
4227                 blendStateExt.getEnabledMask().test(drawBufferIndex) &&
4228                 blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex))
4229             {
4230                 ++advancedBlendRenderTargetCount;
4231             }
4232         }
4233 
4234         if (advancedBlendRenderTargetCount > 1)
4235         {
4236             return kAdvancedBlendEquationWithMRT;
4237         }
4238     }
4239 
4240     if (context->getStateCache().hasAnyEnabledClientAttrib())
4241     {
4242         if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled())
4243         {
4244             // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
4245             // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
4246             // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
4247             // to drawArrays or drawElements will generate an INVALID_OPERATION error.
4248             return kVertexArrayNoBuffer;
4249         }
4250 
4251         if (state.getVertexArray()->hasEnabledNullPointerClientArray())
4252         {
4253             // This is an application error that would normally result in a crash, but we catch it
4254             // and return an error
4255             return kVertexArrayNoBufferPointer;
4256         }
4257     }
4258 
4259     // If we are running GLES1, there is no current program.
4260     if (context->getClientVersion() >= Version(2, 0))
4261     {
4262         Program *program                    = state.getLinkedProgram(context);
4263         ProgramPipeline *programPipeline    = state.getLinkedProgramPipeline(context);
4264         const ProgramExecutable *executable = state.getProgramExecutable();
4265 
4266         bool programIsYUVOutput = false;
4267 
4268         if (program)
4269         {
4270             const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
4271             if (errorMsg)
4272             {
4273                 return errorMsg;
4274             }
4275 
4276             programIsYUVOutput = executable->isYUVOutput();
4277         }
4278         else if (programPipeline)
4279         {
4280             const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
4281             if (errorMsg)
4282             {
4283                 return errorMsg;
4284             }
4285 
4286             errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline);
4287             if (errorMsg)
4288             {
4289                 return errorMsg;
4290             }
4291 
4292             if (!programPipeline->isLinked())
4293             {
4294                 return kProgramPipelineLinkFailed;
4295             }
4296 
4297             programIsYUVOutput = executable->isYUVOutput();
4298         }
4299 
4300         if (executable)
4301         {
4302             if (!executable->validateSamplers(nullptr, context->getCaps()))
4303             {
4304                 return kTextureTypeConflict;
4305             }
4306 
4307             if (executable->hasLinkedTessellationShader())
4308             {
4309                 if (!executable->hasLinkedShaderStage(ShaderType::Vertex))
4310                 {
4311                     return kTessellationShaderRequiresVertexShader;
4312                 }
4313 
4314                 if (!executable->hasLinkedShaderStage(ShaderType::TessControl) ||
4315                     !executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
4316                 {
4317                     return kTessellationShaderRequiresBothControlAndEvaluation;
4318                 }
4319             }
4320 
4321             if (state.isTransformFeedbackActive())
4322             {
4323                 if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
4324                 {
4325                     return kTransformFeedbackBufferMissing;
4326                 }
4327             }
4328         }
4329 
4330         if (programIsYUVOutput != framebufferIsYUV)
4331         {
4332             // Both the program and framebuffer must match in YUV output state.
4333             return kYUVOutputMissmatch;
4334         }
4335 
4336         if (!state.validateSamplerFormats())
4337         {
4338             return kSamplerFormatMismatch;
4339         }
4340 
4341         // Do some additional WebGL-specific validation
4342         if (extensions.webglCompatibilityANGLE)
4343         {
4344             const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
4345             if (state.isTransformFeedbackActive() &&
4346                 transformFeedbackObject->buffersBoundForOtherUseInWebGL())
4347             {
4348                 return kTransformFeedbackBufferDoubleBound;
4349             }
4350 
4351             // Detect rendering feedback loops for WebGL.
4352             if (framebuffer->formsRenderingFeedbackLoopWith(context))
4353             {
4354                 return kFeedbackLoop;
4355             }
4356 
4357             // Detect that the vertex shader input types match the attribute types
4358             if (!ValidateVertexShaderAttributeTypeMatch(context))
4359             {
4360                 return kVertexShaderTypeMismatch;
4361             }
4362 
4363             if (!context->getState().getRasterizerState().rasterizerDiscard &&
4364                 !context->getState().allActiveDrawBufferChannelsMasked())
4365             {
4366                 // Detect that if there's active color buffer without fragment shader output
4367                 if (!ValidateFragmentShaderColorBufferMaskMatch(context))
4368                 {
4369                     return kDrawBufferMaskMismatch;
4370                 }
4371 
4372                 // Detect that the color buffer types match the fragment shader output types
4373                 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
4374                 {
4375                     return kDrawBufferTypeMismatch;
4376                 }
4377             }
4378 
4379             const VertexArray *vao = context->getState().getVertexArray();
4380             if (vao->hasTransformFeedbackBindingConflict(context))
4381             {
4382                 return kVertexBufferBoundForTransformFeedback;
4383             }
4384 
4385             // Validate that we are rendering with a linked program.
4386             if (!program->isLinked())
4387             {
4388                 return kProgramNotLinked;
4389             }
4390         }
4391     }
4392 
4393     *outErrorCode = GL_NO_ERROR;
4394     return nullptr;
4395 }
4396 
ValidateProgramPipeline(const Context * context)4397 const char *ValidateProgramPipeline(const Context *context)
4398 {
4399     const State &state = context->getState();
4400     // If we are running GLES1, there is no current program.
4401     if (context->getClientVersion() >= Version(2, 0))
4402     {
4403         ProgramPipeline *programPipeline = state.getProgramPipeline();
4404         if (programPipeline)
4405         {
4406             const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
4407             if (errorMsg)
4408             {
4409                 return errorMsg;
4410             }
4411         }
4412     }
4413     return nullptr;
4414 }
4415 
RecordDrawModeError(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode)4416 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode)
4417 {
4418     const State &state                      = context->getState();
4419     TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
4420     if (state.isTransformFeedbackActiveUnpaused())
4421     {
4422         if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint,
4423                                                     curTransformFeedback->getPrimitiveMode(), mode))
4424         {
4425             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
4426             return;
4427         }
4428     }
4429 
4430     const Extensions &extensions = context->getExtensions();
4431 
4432     switch (mode)
4433     {
4434         case PrimitiveMode::Points:
4435         case PrimitiveMode::Lines:
4436         case PrimitiveMode::LineLoop:
4437         case PrimitiveMode::LineStrip:
4438         case PrimitiveMode::Triangles:
4439         case PrimitiveMode::TriangleStrip:
4440         case PrimitiveMode::TriangleFan:
4441             break;
4442 
4443         case PrimitiveMode::LinesAdjacency:
4444         case PrimitiveMode::LineStripAdjacency:
4445         case PrimitiveMode::TrianglesAdjacency:
4446         case PrimitiveMode::TriangleStripAdjacency:
4447             if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2)
4448             {
4449                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4450                 return;
4451             }
4452             break;
4453 
4454         case PrimitiveMode::Patches:
4455             if (!extensions.tessellationShaderEXT && context->getClientVersion() < ES_3_2)
4456             {
4457                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderExtensionNotEnabled);
4458                 return;
4459             }
4460             break;
4461 
4462         default:
4463             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawMode);
4464             return;
4465     }
4466 
4467     // If we are running GLES1, there is no current program.
4468     if (context->getClientVersion() >= Version(2, 0))
4469     {
4470         const ProgramExecutable *executable = state.getProgramExecutable();
4471         ASSERT(executable);
4472 
4473         // Do geometry shader specific validations
4474         if (executable->hasLinkedShaderStage(ShaderType::Geometry))
4475         {
4476             if (!IsCompatibleDrawModeWithGeometryShader(
4477                     mode, executable->getGeometryShaderInputPrimitiveType()))
4478             {
4479                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4480                                        kIncompatibleDrawModeAgainstGeometryShader);
4481                 return;
4482             }
4483         }
4484 
4485         if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches)
4486         {
4487             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4488                                    kIncompatibleDrawModeWithTessellationShader);
4489             return;
4490         }
4491 
4492         if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches)
4493         {
4494             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4495                                    kIncompatibleDrawModeWithoutTessellationShader);
4496             return;
4497         }
4498     }
4499 
4500     // An error should be recorded.
4501     UNREACHABLE();
4502 }
4503 
ValidateDrawArraysInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4504 bool ValidateDrawArraysInstancedANGLE(const Context *context,
4505                                       angle::EntryPoint entryPoint,
4506                                       PrimitiveMode mode,
4507                                       GLint first,
4508                                       GLsizei count,
4509                                       GLsizei primcount)
4510 {
4511     if (!context->getExtensions().instancedArraysANGLE)
4512     {
4513         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4514         return false;
4515     }
4516 
4517     if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
4518     {
4519         return false;
4520     }
4521 
4522     return ValidateDrawInstancedANGLE(context, entryPoint);
4523 }
4524 
ValidateDrawArraysInstancedEXT(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4525 bool ValidateDrawArraysInstancedEXT(const Context *context,
4526                                     angle::EntryPoint entryPoint,
4527                                     PrimitiveMode mode,
4528                                     GLint first,
4529                                     GLsizei count,
4530                                     GLsizei primcount)
4531 {
4532     if (!context->getExtensions().instancedArraysEXT)
4533     {
4534         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4535         return false;
4536     }
4537 
4538     if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
4539     {
4540         return false;
4541     }
4542 
4543     return true;
4544 }
4545 
ValidateDrawElementsStates(const Context * context)4546 const char *ValidateDrawElementsStates(const Context *context)
4547 {
4548     const State &state = context->getState();
4549 
4550     if (context->getStateCache().isTransformFeedbackActiveUnpaused())
4551     {
4552         // EXT_geometry_shader allows transform feedback to work with all draw commands.
4553         // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
4554         if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2)
4555         {
4556             // It is an invalid operation to call DrawElements, DrawRangeElements or
4557             // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
4558             // 86)
4559             return kUnsupportedDrawModeForTransformFeedback;
4560         }
4561     }
4562 
4563     const VertexArray *vao     = state.getVertexArray();
4564     Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
4565 
4566     if (elementArrayBuffer)
4567     {
4568         if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
4569         {
4570             return kElementArrayBufferBoundForTransformFeedback;
4571         }
4572         if (elementArrayBuffer->isMapped() &&
4573             (!elementArrayBuffer->isImmutable() ||
4574              (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0))
4575         {
4576             return kBufferMapped;
4577         }
4578     }
4579     else
4580     {
4581         // [WebGL 1.0] Section 6.2 No Client Side Arrays
4582         // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
4583         // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
4584         if (!context->getState().areClientArraysEnabled() || context->isWebGL())
4585         {
4586             return kMustHaveElementArrayBinding;
4587         }
4588     }
4589 
4590     return nullptr;
4591 }
4592 
ValidateDrawElementsInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)4593 bool ValidateDrawElementsInstancedANGLE(const Context *context,
4594                                         angle::EntryPoint entryPoint,
4595                                         PrimitiveMode mode,
4596                                         GLsizei count,
4597                                         DrawElementsType type,
4598                                         const void *indices,
4599                                         GLsizei primcount)
4600 {
4601     if (!context->getExtensions().instancedArraysANGLE)
4602     {
4603         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4604         return false;
4605     }
4606 
4607     if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
4608                                            primcount))
4609     {
4610         return false;
4611     }
4612 
4613     return ValidateDrawInstancedANGLE(context, entryPoint);
4614 }
4615 
ValidateDrawElementsInstancedEXT(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)4616 bool ValidateDrawElementsInstancedEXT(const Context *context,
4617                                       angle::EntryPoint entryPoint,
4618                                       PrimitiveMode mode,
4619                                       GLsizei count,
4620                                       DrawElementsType type,
4621                                       const void *indices,
4622                                       GLsizei primcount)
4623 {
4624     if (!context->getExtensions().instancedArraysEXT)
4625     {
4626         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4627         return false;
4628     }
4629 
4630     if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
4631                                            primcount))
4632     {
4633         return false;
4634     }
4635 
4636     return true;
4637 }
4638 
ValidateGetUniformBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location)4639 bool ValidateGetUniformBase(const Context *context,
4640                             angle::EntryPoint entryPoint,
4641                             ShaderProgramID program,
4642                             UniformLocation location)
4643 {
4644     if (program.value == 0)
4645     {
4646         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kProgramDoesNotExist);
4647         return false;
4648     }
4649 
4650     Program *programObject = GetValidProgram(context, entryPoint, program);
4651     if (!programObject)
4652     {
4653         return false;
4654     }
4655 
4656     if (!programObject || !programObject->isLinked())
4657     {
4658         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
4659         return false;
4660     }
4661 
4662     if (!programObject->isValidUniformLocation(location))
4663     {
4664         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
4665         return false;
4666     }
4667 
4668     return true;
4669 }
4670 
ValidateSizedGetUniform(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,GLsizei * length)4671 bool ValidateSizedGetUniform(const Context *context,
4672                              angle::EntryPoint entryPoint,
4673                              ShaderProgramID program,
4674                              UniformLocation location,
4675                              GLsizei bufSize,
4676                              GLsizei *length)
4677 {
4678     if (length)
4679     {
4680         *length = 0;
4681     }
4682 
4683     if (!ValidateGetUniformBase(context, entryPoint, program, location))
4684     {
4685         return false;
4686     }
4687 
4688     if (bufSize < 0)
4689     {
4690         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNegativeBufferSize);
4691         return false;
4692     }
4693 
4694     Program *programObject = context->getProgramResolveLink(program);
4695     ASSERT(programObject);
4696 
4697     // sized queries -- ensure the provided buffer is large enough
4698     const LinkedUniform &uniform = programObject->getUniformByLocation(location);
4699     size_t requiredBytes         = VariableExternalSize(uniform.getType());
4700     if (static_cast<size_t>(bufSize) < requiredBytes)
4701     {
4702         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
4703         return false;
4704     }
4705 
4706     if (length)
4707     {
4708         *length = VariableComponentCount(uniform.getType());
4709     }
4710     return true;
4711 }
4712 
ValidateGetnUniformfvEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLfloat * params)4713 bool ValidateGetnUniformfvEXT(const Context *context,
4714                               angle::EntryPoint entryPoint,
4715                               ShaderProgramID program,
4716                               UniformLocation location,
4717                               GLsizei bufSize,
4718                               const GLfloat *params)
4719 {
4720     return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
4721 }
4722 
ValidateGetnUniformfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4723 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
4724                                       angle::EntryPoint entryPoint,
4725                                       ShaderProgramID program,
4726                                       UniformLocation location,
4727                                       GLsizei bufSize,
4728                                       const GLsizei *length,
4729                                       const GLfloat *params)
4730 {
4731     UNIMPLEMENTED();
4732     return false;
4733 }
4734 
ValidateGetnUniformivEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLint * params)4735 bool ValidateGetnUniformivEXT(const Context *context,
4736                               angle::EntryPoint entryPoint,
4737                               ShaderProgramID program,
4738                               UniformLocation location,
4739                               GLsizei bufSize,
4740                               const GLint *params)
4741 {
4742     return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
4743 }
4744 
ValidateGetnUniformivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)4745 bool ValidateGetnUniformivRobustANGLE(const Context *context,
4746                                       angle::EntryPoint entryPoint,
4747                                       ShaderProgramID program,
4748                                       UniformLocation location,
4749                                       GLsizei bufSize,
4750                                       const GLsizei *length,
4751                                       const GLint *params)
4752 {
4753     UNIMPLEMENTED();
4754     return false;
4755 }
4756 
ValidateGetnUniformuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)4757 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
4758                                        angle::EntryPoint entryPoint,
4759                                        ShaderProgramID program,
4760                                        UniformLocation location,
4761                                        GLsizei bufSize,
4762                                        const GLsizei *length,
4763                                        const GLuint *params)
4764 {
4765     UNIMPLEMENTED();
4766     return false;
4767 }
4768 
ValidateGetUniformfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4769 bool ValidateGetUniformfvRobustANGLE(const Context *context,
4770                                      angle::EntryPoint entryPoint,
4771                                      ShaderProgramID program,
4772                                      UniformLocation location,
4773                                      GLsizei bufSize,
4774                                      const GLsizei *length,
4775                                      const GLfloat *params)
4776 {
4777     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4778     {
4779         return false;
4780     }
4781 
4782     GLsizei writeLength = 0;
4783 
4784     // bufSize is validated in ValidateSizedGetUniform
4785     if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
4786     {
4787         return false;
4788     }
4789 
4790     SetRobustLengthParam(length, writeLength);
4791 
4792     return true;
4793 }
4794 
ValidateGetUniformivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)4795 bool ValidateGetUniformivRobustANGLE(const Context *context,
4796                                      angle::EntryPoint entryPoint,
4797                                      ShaderProgramID program,
4798                                      UniformLocation location,
4799                                      GLsizei bufSize,
4800                                      const GLsizei *length,
4801                                      const GLint *params)
4802 {
4803     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4804     {
4805         return false;
4806     }
4807 
4808     GLsizei writeLength = 0;
4809 
4810     // bufSize is validated in ValidateSizedGetUniform
4811     if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
4812     {
4813         return false;
4814     }
4815 
4816     SetRobustLengthParam(length, writeLength);
4817 
4818     return true;
4819 }
4820 
ValidateGetUniformuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)4821 bool ValidateGetUniformuivRobustANGLE(const Context *context,
4822                                       angle::EntryPoint entryPoint,
4823                                       ShaderProgramID program,
4824                                       UniformLocation location,
4825                                       GLsizei bufSize,
4826                                       const GLsizei *length,
4827                                       const GLuint *params)
4828 {
4829     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4830     {
4831         return false;
4832     }
4833 
4834     if (context->getClientMajorVersion() < 3)
4835     {
4836         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4837         return false;
4838     }
4839 
4840     GLsizei writeLength = 0;
4841 
4842     // bufSize is validated in ValidateSizedGetUniform
4843     if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
4844     {
4845         return false;
4846     }
4847 
4848     SetRobustLengthParam(length, writeLength);
4849 
4850     return true;
4851 }
4852 
ValidateDiscardFramebufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments,bool defaultFramebuffer)4853 bool ValidateDiscardFramebufferBase(const Context *context,
4854                                     angle::EntryPoint entryPoint,
4855                                     GLenum target,
4856                                     GLsizei numAttachments,
4857                                     const GLenum *attachments,
4858                                     bool defaultFramebuffer)
4859 {
4860     if (numAttachments < 0)
4861     {
4862         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeAttachments);
4863         return false;
4864     }
4865 
4866     for (GLsizei i = 0; i < numAttachments; ++i)
4867     {
4868         if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
4869         {
4870             if (defaultFramebuffer)
4871             {
4872                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
4873                 return false;
4874             }
4875 
4876             if (attachments[i] >=
4877                 GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
4878             {
4879                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
4880                 return false;
4881             }
4882         }
4883         else
4884         {
4885             switch (attachments[i])
4886             {
4887                 case GL_DEPTH_ATTACHMENT:
4888                 case GL_STENCIL_ATTACHMENT:
4889                 case GL_DEPTH_STENCIL_ATTACHMENT:
4890                     if (defaultFramebuffer)
4891                     {
4892                         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
4893                                                kDefaultFramebufferInvalidAttachment);
4894                         return false;
4895                     }
4896                     break;
4897                 case GL_COLOR:
4898                 case GL_DEPTH:
4899                 case GL_STENCIL:
4900                     if (!defaultFramebuffer)
4901                     {
4902                         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
4903                                                kDefaultFramebufferAttachmentOnUserFBO);
4904                         return false;
4905                     }
4906                     break;
4907                 default:
4908                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
4909                     return false;
4910             }
4911         }
4912     }
4913 
4914     return true;
4915 }
4916 
ValidateInsertEventMarkerEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei length,const char * marker)4917 bool ValidateInsertEventMarkerEXT(const Context *context,
4918                                   angle::EntryPoint entryPoint,
4919                                   GLsizei length,
4920                                   const char *marker)
4921 {
4922     if (!context->getExtensions().debugMarkerEXT)
4923     {
4924         // The debug marker calls should not set error state
4925         // However, it seems reasonable to set an error state if the extension is not enabled
4926         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4927         return false;
4928     }
4929 
4930     // Note that debug marker calls must not set error state
4931     if (length < 0)
4932     {
4933         return false;
4934     }
4935 
4936     if (marker == nullptr)
4937     {
4938         return false;
4939     }
4940 
4941     return true;
4942 }
4943 
ValidatePushGroupMarkerEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei length,const char * marker)4944 bool ValidatePushGroupMarkerEXT(const Context *context,
4945                                 angle::EntryPoint entryPoint,
4946                                 GLsizei length,
4947                                 const char *marker)
4948 {
4949     if (!context->getExtensions().debugMarkerEXT)
4950     {
4951         // The debug marker calls should not set error state
4952         // However, it seems reasonable to set an error state if the extension is not enabled
4953         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4954         return false;
4955     }
4956 
4957     // Note that debug marker calls must not set error state
4958     if (length < 0)
4959     {
4960         return false;
4961     }
4962 
4963     if (length > 0 && marker == nullptr)
4964     {
4965         return false;
4966     }
4967 
4968     return true;
4969 }
4970 
ValidateEGLImageObject(const Context * context,angle::EntryPoint entryPoint,TextureType type,egl::ImageID imageID)4971 bool ValidateEGLImageObject(const Context *context,
4972                             angle::EntryPoint entryPoint,
4973                             TextureType type,
4974                             egl::ImageID imageID)
4975 {
4976     ASSERT(context->getDisplay());
4977     if (!context->getDisplay()->isValidImage(imageID))
4978     {
4979         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
4980         return false;
4981     }
4982 
4983     egl::Image *imageObject = context->getDisplay()->getImage(imageID);
4984     if (imageObject->getSamples() > 0)
4985     {
4986         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
4987         return false;
4988     }
4989 
4990     if (!imageObject->isTexturable(context))
4991     {
4992         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
4993         return false;
4994     }
4995 
4996     // Validate source egl image and target texture are compatible
4997     size_t depth = static_cast<size_t>(imageObject->getExtents().depth);
4998     if (imageObject->isYUV() && type != TextureType::External)
4999     {
5000         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5001                                "Image is YUV, target must be TEXTURE_EXTERNAL_OES");
5002         return false;
5003     }
5004 
5005     if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap &&
5006         type != TextureType::CubeMapArray && type != TextureType::_3D)
5007     {
5008         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5009         return false;
5010     }
5011 
5012     if (imageObject->isCubeMap() && type != TextureType::CubeMapArray &&
5013         (type != TextureType::CubeMap || depth > gl::kCubeFaceCount))
5014     {
5015         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5016         return false;
5017     }
5018 
5019     if (imageObject->getLevelCount() > 1 && type == TextureType::External)
5020     {
5021         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5022         return false;
5023     }
5024 
5025     // 3d EGLImages are currently not supported
5026     if (type == TextureType::_3D)
5027     {
5028         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5029         return false;
5030     }
5031 
5032     if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent())
5033     {
5034         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5035                                "Mismatch between Image and Context Protected Content state");
5036         return false;
5037     }
5038 
5039     return true;
5040 }
5041 
ValidateEGLImageTargetTexture2DOES(const Context * context,angle::EntryPoint entryPoint,TextureType type,egl::ImageID image)5042 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
5043                                         angle::EntryPoint entryPoint,
5044                                         TextureType type,
5045                                         egl::ImageID image)
5046 {
5047     if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES)
5048     {
5049         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5050         return false;
5051     }
5052 
5053     switch (type)
5054     {
5055         case TextureType::_2D:
5056             if (!context->getExtensions().EGLImageOES)
5057             {
5058                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5059             }
5060             break;
5061 
5062         case TextureType::_2DArray:
5063             if (!context->getExtensions().EGLImageArrayEXT)
5064             {
5065                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5066             }
5067             break;
5068 
5069         case TextureType::External:
5070             if (!context->getExtensions().EGLImageExternalOES)
5071             {
5072                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5073             }
5074             break;
5075 
5076         default:
5077             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
5078             return false;
5079     }
5080 
5081     return ValidateEGLImageObject(context, entryPoint, type, image);
5082 }
5083 
ValidateEGLImageTargetRenderbufferStorageOES(const Context * context,angle::EntryPoint entryPoint,GLenum target,egl::ImageID image)5084 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
5085                                                   angle::EntryPoint entryPoint,
5086                                                   GLenum target,
5087                                                   egl::ImageID image)
5088 {
5089     if (!context->getExtensions().EGLImageOES)
5090     {
5091         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5092         return false;
5093     }
5094 
5095     switch (target)
5096     {
5097         case GL_RENDERBUFFER:
5098             break;
5099 
5100         default:
5101             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
5102             return false;
5103     }
5104 
5105     ASSERT(context->getDisplay());
5106     if (!context->getDisplay()->isValidImage(image))
5107     {
5108         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
5109         return false;
5110     }
5111 
5112     egl::Image *imageObject = context->getDisplay()->getImage(image);
5113     if (!imageObject->isRenderable(context))
5114     {
5115         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
5116         return false;
5117     }
5118 
5119     if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
5120     {
5121         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5122                                "Mismatch between Image and Context Protected Content state");
5123         return false;
5124     }
5125 
5126     return true;
5127 }
5128 
ValidateProgramBinaryBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)5129 bool ValidateProgramBinaryBase(const Context *context,
5130                                angle::EntryPoint entryPoint,
5131                                ShaderProgramID program,
5132                                GLenum binaryFormat,
5133                                const void *binary,
5134                                GLint length)
5135 {
5136     Program *programObject = GetValidProgram(context, entryPoint, program);
5137     if (programObject == nullptr)
5138     {
5139         return false;
5140     }
5141 
5142     const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
5143     if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
5144         programBinaryFormats.end())
5145     {
5146         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
5147         return false;
5148     }
5149 
5150     if (context->hasActiveTransformFeedback(program))
5151     {
5152         // ES 3.0.4 section 2.15 page 91
5153         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
5154         return false;
5155     }
5156 
5157     return true;
5158 }
5159 
ValidateGetProgramBinaryBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)5160 bool ValidateGetProgramBinaryBase(const Context *context,
5161                                   angle::EntryPoint entryPoint,
5162                                   ShaderProgramID program,
5163                                   GLsizei bufSize,
5164                                   const GLsizei *length,
5165                                   const GLenum *binaryFormat,
5166                                   const void *binary)
5167 {
5168     Program *programObject = GetValidProgram(context, entryPoint, program);
5169     if (programObject == nullptr)
5170     {
5171         return false;
5172     }
5173 
5174     if (!programObject->isLinked())
5175     {
5176         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
5177         return false;
5178     }
5179 
5180     if (context->getCaps().programBinaryFormats.empty())
5181     {
5182         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
5183         return false;
5184     }
5185 
5186     return true;
5187 }
5188 
ValidateDrawBuffersBase(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const GLenum * bufs)5189 bool ValidateDrawBuffersBase(const Context *context,
5190                              angle::EntryPoint entryPoint,
5191                              GLsizei n,
5192                              const GLenum *bufs)
5193 {
5194     // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
5195     if (n < 0)
5196     {
5197         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
5198         return false;
5199     }
5200     if (n > context->getCaps().maxDrawBuffers)
5201     {
5202         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
5203         return false;
5204     }
5205 
5206     ASSERT(context->getState().getDrawFramebuffer());
5207     FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
5208     GLuint maxColorAttachment   = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
5209 
5210     // This should come first before the check for the default frame buffer
5211     // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
5212     // rather than INVALID_OPERATION
5213     for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
5214     {
5215         const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
5216 
5217         if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
5218             (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
5219              bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
5220         {
5221             // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
5222             // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
5223             // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
5224             // 3.1 is still a bit ambiguous about the error, but future specs are
5225             // expected to clarify that GL_INVALID_ENUM is the correct error.
5226             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawBuffer);
5227             return false;
5228         }
5229         else if (bufs[colorAttachment] >= maxColorAttachment)
5230         {
5231             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
5232             return false;
5233         }
5234         else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
5235                  frameBufferId.value != 0)
5236         {
5237             // INVALID_OPERATION-GL is bound to buffer and ith argument
5238             // is not COLOR_ATTACHMENTi or NONE
5239             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
5240             return false;
5241         }
5242     }
5243 
5244     // INVALID_OPERATION is generated if GL is bound to the default framebuffer
5245     // and n is not 1 or bufs is bound to value other than BACK and NONE
5246     if (frameBufferId.value == 0)
5247     {
5248         if (n != 1)
5249         {
5250             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
5251             return false;
5252         }
5253 
5254         if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
5255         {
5256             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
5257             return false;
5258         }
5259     }
5260 
5261     return true;
5262 }
5263 
ValidateGetBufferPointervBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei * length,void * const * params)5264 bool ValidateGetBufferPointervBase(const Context *context,
5265                                    angle::EntryPoint entryPoint,
5266                                    BufferBinding target,
5267                                    GLenum pname,
5268                                    GLsizei *length,
5269                                    void *const *params)
5270 {
5271     if (length)
5272     {
5273         *length = 0;
5274     }
5275 
5276     if (!context->isValidBufferBinding(target))
5277     {
5278         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5279         return false;
5280     }
5281 
5282     switch (pname)
5283     {
5284         case GL_BUFFER_MAP_POINTER:
5285             break;
5286 
5287         default:
5288             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5289             return false;
5290     }
5291 
5292     // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
5293     // target bound to zero generate an INVALID_OPERATION error."
5294     // GLES 3.1 section 6.6 explicitly specifies this error.
5295     if (context->getState().getTargetBuffer(target) == nullptr)
5296     {
5297         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
5298         return false;
5299     }
5300 
5301     if (length)
5302     {
5303         *length = 1;
5304     }
5305 
5306     return true;
5307 }
5308 
ValidateUnmapBufferBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target)5309 bool ValidateUnmapBufferBase(const Context *context,
5310                              angle::EntryPoint entryPoint,
5311                              BufferBinding target)
5312 {
5313     if (!context->isValidBufferBinding(target))
5314     {
5315         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5316         return false;
5317     }
5318 
5319     Buffer *buffer = context->getState().getTargetBuffer(target);
5320 
5321     if (buffer == nullptr || !buffer->isMapped())
5322     {
5323         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMapped);
5324         return false;
5325     }
5326 
5327     return true;
5328 }
5329 
ValidateMapBufferRangeBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)5330 bool ValidateMapBufferRangeBase(const Context *context,
5331                                 angle::EntryPoint entryPoint,
5332                                 BufferBinding target,
5333                                 GLintptr offset,
5334                                 GLsizeiptr length,
5335                                 GLbitfield access)
5336 {
5337     if (!context->isValidBufferBinding(target))
5338     {
5339         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5340         return false;
5341     }
5342 
5343     if (offset < 0)
5344     {
5345         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
5346         return false;
5347     }
5348 
5349     if (length < 0)
5350     {
5351         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength);
5352         return false;
5353     }
5354 
5355     Buffer *buffer = context->getState().getTargetBuffer(target);
5356 
5357     if (!buffer)
5358     {
5359         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMappable);
5360         return false;
5361     }
5362 
5363     // Check for buffer overflow
5364     CheckedNumeric<size_t> checkedOffset(offset);
5365     auto checkedSize = checkedOffset + length;
5366 
5367     if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
5368     {
5369         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMapOutOfRange);
5370         return false;
5371     }
5372 
5373     // Check for invalid bits in the mask
5374     constexpr GLbitfield kAllAccessBits =
5375         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
5376         GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5377 
5378     if (buffer->isImmutable())
5379     {
5380         // GL_EXT_buffer_storage's additions to glMapBufferRange
5381         constexpr GLbitfield kBufferStorageAccessBits =
5382             kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT;
5383 
5384         if ((access & ~kBufferStorageAccessBits) != 0)
5385         {
5386             ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
5387             return false;
5388         }
5389 
5390         // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access,
5391         // but the same bits are not included in the buffer's storage flags
5392         constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
5393                                                                GL_MAP_PERSISTENT_BIT_EXT |
5394                                                                GL_MAP_COHERENT_BIT_EXT;
5395         GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits;
5396         if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags)
5397         {
5398             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBits);
5399             return false;
5400         }
5401     }
5402     else if ((access & ~kAllAccessBits) != 0)
5403     {
5404         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
5405         return false;
5406     }
5407 
5408     if (length == 0)
5409     {
5410         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kLengthZero);
5411         return false;
5412     }
5413 
5414     if (buffer->isMapped())
5415     {
5416         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferAlreadyMapped);
5417         return false;
5418     }
5419 
5420     // Check for invalid bit combinations
5421     if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
5422     {
5423         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
5424         return false;
5425     }
5426 
5427     GLbitfield writeOnlyBits =
5428         GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5429 
5430     if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
5431     {
5432         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
5433         return false;
5434     }
5435 
5436     if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
5437     {
5438         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
5439         return false;
5440     }
5441 
5442     return ValidateMapBufferBase(context, entryPoint, target);
5443 }
5444 
ValidateFlushMappedBufferRangeBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length)5445 bool ValidateFlushMappedBufferRangeBase(const Context *context,
5446                                         angle::EntryPoint entryPoint,
5447                                         BufferBinding target,
5448                                         GLintptr offset,
5449                                         GLsizeiptr length)
5450 {
5451     if (offset < 0)
5452     {
5453         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
5454         return false;
5455     }
5456 
5457     if (length < 0)
5458     {
5459         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength);
5460         return false;
5461     }
5462 
5463     if (!context->isValidBufferBinding(target))
5464     {
5465         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5466         return false;
5467     }
5468 
5469     Buffer *buffer = context->getState().getTargetBuffer(target);
5470 
5471     if (buffer == nullptr)
5472     {
5473         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFlushZero);
5474         return false;
5475     }
5476 
5477     if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
5478     {
5479         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFlushTarget);
5480         return false;
5481     }
5482 
5483     // Check for buffer overflow
5484     CheckedNumeric<size_t> checkedOffset(offset);
5485     auto checkedSize = checkedOffset + length;
5486 
5487     if (!checkedSize.IsValid() ||
5488         checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
5489     {
5490         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
5491         return false;
5492     }
5493 
5494     return true;
5495 }
5496 
ValidateGenOrDelete(const Context * context,angle::EntryPoint entryPoint,GLint n)5497 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n)
5498 {
5499     if (n < 0)
5500     {
5501         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
5502         return false;
5503     }
5504     return true;
5505 }
5506 
ValidateRobustEntryPoint(const Context * context,angle::EntryPoint entryPoint,GLsizei bufSize)5507 bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize)
5508 {
5509     if (!context->getExtensions().robustClientMemoryANGLE)
5510     {
5511         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5512         return false;
5513     }
5514 
5515     if (bufSize < 0)
5516     {
5517         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
5518         return false;
5519     }
5520 
5521     return true;
5522 }
5523 
ValidateRobustBufferSize(const Context * context,angle::EntryPoint entryPoint,GLsizei bufSize,GLsizei numParams)5524 bool ValidateRobustBufferSize(const Context *context,
5525                               angle::EntryPoint entryPoint,
5526                               GLsizei bufSize,
5527                               GLsizei numParams)
5528 {
5529     if (bufSize < numParams)
5530     {
5531         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientParams);
5532         return false;
5533     }
5534 
5535     return true;
5536 }
5537 
ValidateGetFramebufferAttachmentParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum pname,GLsizei * numParams)5538 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
5539                                                      angle::EntryPoint entryPoint,
5540                                                      GLenum target,
5541                                                      GLenum attachment,
5542                                                      GLenum pname,
5543                                                      GLsizei *numParams)
5544 {
5545     if (!ValidFramebufferTarget(context, target))
5546     {
5547         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
5548         return false;
5549     }
5550 
5551     int clientVersion = context->getClientMajorVersion();
5552 
5553     switch (pname)
5554     {
5555         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5556         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5557         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5558         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5559             break;
5560 
5561         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
5562         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
5563             if (clientVersion < 3 ||
5564                 !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
5565             {
5566                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5567                 return false;
5568             }
5569             break;
5570 
5571         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
5572             if (!context->getExtensions().multisampledRenderToTextureEXT)
5573             {
5574                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5575                 return false;
5576             }
5577             break;
5578 
5579         case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
5580             if (clientVersion < 3 && !context->getExtensions().sRGBEXT)
5581             {
5582                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5583                 return false;
5584             }
5585             break;
5586 
5587         case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5588             if (clientVersion < 3 && !context->getExtensions().colorBufferHalfFloatEXT &&
5589                 !context->getExtensions().colorBufferFloatRgbCHROMIUM &&
5590                 !context->getExtensions().colorBufferFloatRgbaCHROMIUM)
5591             {
5592                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5593                 return false;
5594             }
5595             break;
5596 
5597         case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
5598         case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
5599         case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
5600         case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
5601         case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
5602         case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
5603         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5604             if (clientVersion < 3)
5605             {
5606                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
5607                 return false;
5608             }
5609             break;
5610 
5611         case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
5612             if (!context->getExtensions().geometryShaderAny() &&
5613                 context->getClientVersion() < ES_3_2)
5614             {
5615                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
5616                 return false;
5617             }
5618             break;
5619 
5620         default:
5621             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
5622             return false;
5623     }
5624 
5625     // Determine if the attachment is a valid enum
5626     switch (attachment)
5627     {
5628         case GL_BACK:
5629         case GL_DEPTH:
5630         case GL_STENCIL:
5631             if (clientVersion < 3)
5632             {
5633                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5634                 return false;
5635             }
5636             break;
5637 
5638         case GL_DEPTH_STENCIL_ATTACHMENT:
5639             if (clientVersion < 3 && !context->isWebGL1())
5640             {
5641                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5642                 return false;
5643             }
5644             break;
5645 
5646         case GL_COLOR_ATTACHMENT0:
5647         case GL_DEPTH_ATTACHMENT:
5648         case GL_STENCIL_ATTACHMENT:
5649             break;
5650 
5651         default:
5652             if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) ||
5653                 attachment < GL_COLOR_ATTACHMENT0_EXT ||
5654                 (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
5655                     static_cast<GLuint>(context->getCaps().maxColorAttachments))
5656             {
5657                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5658                 return false;
5659             }
5660             break;
5661     }
5662 
5663     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
5664     ASSERT(framebuffer);
5665 
5666     if (framebuffer->isDefault())
5667     {
5668         if (clientVersion < 3)
5669         {
5670             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
5671             return false;
5672         }
5673 
5674         switch (attachment)
5675         {
5676             case GL_BACK:
5677             case GL_DEPTH:
5678             case GL_STENCIL:
5679                 break;
5680 
5681             default:
5682                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5683                 return false;
5684         }
5685     }
5686     else
5687     {
5688         if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5689         {
5690             // Valid attachment query
5691         }
5692         else
5693         {
5694             switch (attachment)
5695             {
5696                 case GL_DEPTH_ATTACHMENT:
5697                 case GL_STENCIL_ATTACHMENT:
5698                     break;
5699 
5700                 case GL_DEPTH_STENCIL_ATTACHMENT:
5701                     if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
5702                     {
5703                         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5704                         return false;
5705                     }
5706                     break;
5707 
5708                 default:
5709                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5710                     return false;
5711             }
5712         }
5713     }
5714 
5715     const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
5716     if (attachmentObject)
5717     {
5718         ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5719                attachmentObject->type() == GL_TEXTURE ||
5720                attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5721 
5722         switch (pname)
5723         {
5724             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5725                 if (attachmentObject->type() != GL_RENDERBUFFER &&
5726                     attachmentObject->type() != GL_TEXTURE)
5727                 {
5728                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5729                     return false;
5730                 }
5731                 break;
5732 
5733             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5734                 if (attachmentObject->type() != GL_TEXTURE)
5735                 {
5736                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5737                     return false;
5738                 }
5739                 break;
5740 
5741             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5742                 if (attachmentObject->type() != GL_TEXTURE)
5743                 {
5744                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5745                     return false;
5746                 }
5747                 break;
5748 
5749             case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5750                 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5751                 {
5752                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5753                     return false;
5754                 }
5755                 break;
5756 
5757             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5758                 if (attachmentObject->type() != GL_TEXTURE)
5759                 {
5760                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5761                     return false;
5762                 }
5763                 break;
5764 
5765             default:
5766                 break;
5767         }
5768     }
5769     else
5770     {
5771         // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5772         // is NONE, then querying any other pname will generate INVALID_ENUM.
5773 
5774         // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5775         // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5776         // INVALID_OPERATION for all other pnames
5777 
5778         switch (pname)
5779         {
5780             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5781                 break;
5782 
5783             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5784                 if (clientVersion < 3)
5785                 {
5786                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
5787                     return false;
5788                 }
5789                 break;
5790 
5791             default:
5792                 if (clientVersion < 3)
5793                 {
5794                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
5795                     return false;
5796                 }
5797                 else
5798                 {
5799                     ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5800                                            kInvalidFramebufferAttachmentParameter);
5801                     return false;
5802                 }
5803         }
5804     }
5805 
5806     if (numParams)
5807     {
5808         *numParams = 1;
5809     }
5810 
5811     return true;
5812 }
5813 
ValidateGetFramebufferParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,const GLint * params)5814 bool ValidateGetFramebufferParameterivBase(const Context *context,
5815                                            angle::EntryPoint entryPoint,
5816                                            GLenum target,
5817                                            GLenum pname,
5818                                            const GLint *params)
5819 {
5820     if (!ValidFramebufferTarget(context, target))
5821     {
5822         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
5823         return false;
5824     }
5825 
5826     switch (pname)
5827     {
5828         case GL_FRAMEBUFFER_DEFAULT_WIDTH:
5829         case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
5830         case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
5831         case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
5832             break;
5833         case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
5834             if (!context->getExtensions().geometryShaderAny() &&
5835                 context->getClientVersion() < ES_3_2)
5836             {
5837                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
5838                 return false;
5839             }
5840             break;
5841         case GL_FRAMEBUFFER_FLIP_Y_MESA:
5842             if (!context->getExtensions().framebufferFlipYMESA)
5843             {
5844                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
5845                 return false;
5846             }
5847             break;
5848         default:
5849             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
5850             return false;
5851     }
5852 
5853     const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
5854     ASSERT(framebuffer);
5855 
5856     if (framebuffer->isDefault())
5857     {
5858         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
5859         return false;
5860     }
5861     return true;
5862 }
5863 
ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5864 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
5865                                                             angle::EntryPoint entryPoint,
5866                                                             GLenum target,
5867                                                             GLenum attachment,
5868                                                             GLenum pname,
5869                                                             GLsizei bufSize,
5870                                                             const GLsizei *length,
5871                                                             const GLint *params)
5872 {
5873     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
5874     {
5875         return false;
5876     }
5877 
5878     GLsizei numParams = 0;
5879     if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
5880                                                          pname, &numParams))
5881     {
5882         return false;
5883     }
5884 
5885     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
5886     {
5887         return false;
5888     }
5889 
5890     SetRobustLengthParam(length, numParams);
5891 
5892     return true;
5893 }
5894 
ValidateGetBufferParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5895 bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
5896                                              angle::EntryPoint entryPoint,
5897                                              BufferBinding target,
5898                                              GLenum pname,
5899                                              GLsizei bufSize,
5900                                              const GLsizei *length,
5901                                              const GLint *params)
5902 {
5903     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
5904     {
5905         return false;
5906     }
5907 
5908     GLsizei numParams = 0;
5909 
5910     if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
5911     {
5912         return false;
5913     }
5914 
5915     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
5916     {
5917         return false;
5918     }
5919 
5920     SetRobustLengthParam(length, numParams);
5921     return true;
5922 }
5923 
ValidateGetBufferParameteri64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint64 * params)5924 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
5925                                                angle::EntryPoint entryPoint,
5926                                                BufferBinding target,
5927                                                GLenum pname,
5928                                                GLsizei bufSize,
5929                                                const GLsizei *length,
5930                                                const GLint64 *params)
5931 {
5932     GLsizei numParams = 0;
5933 
5934     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
5935     {
5936         return false;
5937     }
5938 
5939     if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
5940     {
5941         return false;
5942     }
5943 
5944     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
5945     {
5946         return false;
5947     }
5948 
5949     SetRobustLengthParam(length, numParams);
5950 
5951     return true;
5952 }
5953 
ValidateGetProgramivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLsizei * numParams)5954 bool ValidateGetProgramivBase(const Context *context,
5955                               angle::EntryPoint entryPoint,
5956                               ShaderProgramID program,
5957                               GLenum pname,
5958                               GLsizei *numParams)
5959 {
5960     // Currently, all GetProgramiv queries return 1 parameter
5961     if (numParams)
5962     {
5963         *numParams = 1;
5964     }
5965 
5966     if (context->isContextLost())
5967     {
5968         ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
5969 
5970         if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
5971         {
5972             // Generate an error but still return true, the context still needs to return a
5973             // value in this case.
5974             return true;
5975         }
5976         else
5977         {
5978             return false;
5979         }
5980     }
5981 
5982     // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
5983     Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
5984                                  ? GetValidProgramNoResolve(context, entryPoint, program)
5985                                  : GetValidProgram(context, entryPoint, program);
5986     if (!programObject)
5987     {
5988         return false;
5989     }
5990 
5991     switch (pname)
5992     {
5993         case GL_DELETE_STATUS:
5994         case GL_LINK_STATUS:
5995         case GL_VALIDATE_STATUS:
5996         case GL_INFO_LOG_LENGTH:
5997         case GL_ATTACHED_SHADERS:
5998         case GL_ACTIVE_ATTRIBUTES:
5999         case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
6000         case GL_ACTIVE_UNIFORMS:
6001         case GL_ACTIVE_UNIFORM_MAX_LENGTH:
6002             break;
6003 
6004         case GL_PROGRAM_BINARY_LENGTH:
6005             if (context->getClientMajorVersion() < 3 &&
6006                 !context->getExtensions().getProgramBinaryOES)
6007             {
6008                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6009                 return false;
6010             }
6011             break;
6012 
6013         case GL_ACTIVE_UNIFORM_BLOCKS:
6014         case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
6015         case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
6016         case GL_TRANSFORM_FEEDBACK_VARYINGS:
6017         case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
6018         case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
6019             if (context->getClientMajorVersion() < 3)
6020             {
6021                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
6022                 return false;
6023             }
6024             break;
6025 
6026         case GL_PROGRAM_SEPARABLE:
6027         case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
6028             if (context->getClientVersion() < Version(3, 1))
6029             {
6030                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
6031                 return false;
6032             }
6033             break;
6034 
6035         case GL_COMPUTE_WORK_GROUP_SIZE:
6036             if (context->getClientVersion() < Version(3, 1))
6037             {
6038                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
6039                 return false;
6040             }
6041 
6042             // [OpenGL ES 3.1] Chapter 7.12 Page 122
6043             // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
6044             // program which has not been linked successfully, or which does not contain objects to
6045             // form a compute shader.
6046             if (!programObject->isLinked())
6047             {
6048                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6049                 return false;
6050             }
6051             if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
6052             {
6053                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
6054                 return false;
6055             }
6056             break;
6057 
6058         case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
6059         case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
6060         case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
6061         case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
6062             if (!context->getExtensions().geometryShaderAny() &&
6063                 context->getClientVersion() < ES_3_2)
6064             {
6065                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
6066                 return false;
6067             }
6068 
6069             // [EXT_geometry_shader] Chapter 7.12
6070             // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
6071             // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
6072             // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
6073             // successfully, or which does not contain objects to form a geometry shader.
6074             if (!programObject->isLinked())
6075             {
6076                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6077                 return false;
6078             }
6079             if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
6080             {
6081                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
6082                 return false;
6083             }
6084             break;
6085 
6086         case GL_COMPLETION_STATUS_KHR:
6087             if (!context->getExtensions().parallelShaderCompileKHR)
6088             {
6089                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
6090                 return false;
6091             }
6092             break;
6093         case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
6094         case GL_TESS_GEN_MODE_EXT:
6095         case GL_TESS_GEN_SPACING_EXT:
6096         case GL_TESS_GEN_VERTEX_ORDER_EXT:
6097         case GL_TESS_GEN_POINT_MODE_EXT:
6098             if (!context->getExtensions().tessellationShaderEXT &&
6099                 context->getClientVersion() < ES_3_2)
6100             {
6101                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderExtensionNotEnabled);
6102                 return false;
6103             }
6104             if (!programObject->isLinked())
6105             {
6106                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6107                 return false;
6108             }
6109             break;
6110         default:
6111             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6112             return false;
6113     }
6114 
6115     return true;
6116 }
6117 
ValidateGetProgramivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6118 bool ValidateGetProgramivRobustANGLE(const Context *context,
6119                                      angle::EntryPoint entryPoint,
6120                                      ShaderProgramID program,
6121                                      GLenum pname,
6122                                      GLsizei bufSize,
6123                                      const GLsizei *length,
6124                                      const GLint *params)
6125 {
6126     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6127     {
6128         return false;
6129     }
6130 
6131     GLsizei numParams = 0;
6132 
6133     if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams))
6134     {
6135         return false;
6136     }
6137 
6138     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6139     {
6140         return false;
6141     }
6142 
6143     SetRobustLengthParam(length, numParams);
6144 
6145     return true;
6146 }
6147 
ValidateGetRenderbufferParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6148 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
6149                                                    angle::EntryPoint entryPoint,
6150                                                    GLenum target,
6151                                                    GLenum pname,
6152                                                    GLsizei bufSize,
6153                                                    const GLsizei *length,
6154                                                    const GLint *params)
6155 {
6156     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6157     {
6158         return false;
6159     }
6160 
6161     GLsizei numParams = 0;
6162 
6163     if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams))
6164     {
6165         return false;
6166     }
6167 
6168     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6169     {
6170         return false;
6171     }
6172 
6173     SetRobustLengthParam(length, numParams);
6174 
6175     return true;
6176 }
6177 
ValidateGetShaderivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID shader,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6178 bool ValidateGetShaderivRobustANGLE(const Context *context,
6179                                     angle::EntryPoint entryPoint,
6180                                     ShaderProgramID shader,
6181                                     GLenum pname,
6182                                     GLsizei bufSize,
6183                                     const GLsizei *length,
6184                                     const GLint *params)
6185 {
6186     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6187     {
6188         return false;
6189     }
6190 
6191     GLsizei numParams = 0;
6192 
6193     if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams))
6194     {
6195         return false;
6196     }
6197 
6198     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6199     {
6200         return false;
6201     }
6202 
6203     SetRobustLengthParam(length, numParams);
6204 
6205     return true;
6206 }
6207 
ValidateGetTexParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6208 bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
6209                                           angle::EntryPoint entryPoint,
6210                                           TextureType target,
6211                                           GLenum pname,
6212                                           GLsizei bufSize,
6213                                           const GLsizei *length,
6214                                           const GLfloat *params)
6215 {
6216     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6217     {
6218         return false;
6219     }
6220 
6221     GLsizei numParams = 0;
6222 
6223     if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
6224     {
6225         return false;
6226     }
6227 
6228     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6229     {
6230         return false;
6231     }
6232 
6233     SetRobustLengthParam(length, numParams);
6234 
6235     return true;
6236 }
6237 
ValidateGetTexParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6238 bool ValidateGetTexParameterivRobustANGLE(const Context *context,
6239                                           angle::EntryPoint entryPoint,
6240                                           TextureType target,
6241                                           GLenum pname,
6242                                           GLsizei bufSize,
6243                                           const GLsizei *length,
6244                                           const GLint *params)
6245 {
6246 
6247     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6248     {
6249         return false;
6250     }
6251     GLsizei numParams = 0;
6252     if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
6253     {
6254         return false;
6255     }
6256 
6257     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6258     {
6259         return false;
6260     }
6261 
6262     SetRobustLengthParam(length, numParams);
6263     return true;
6264 }
6265 
ValidateGetTexParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6266 bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
6267                                            angle::EntryPoint entryPoint,
6268                                            TextureType target,
6269                                            GLenum pname,
6270                                            GLsizei bufSize,
6271                                            const GLsizei *length,
6272                                            const GLint *params)
6273 {
6274     UNIMPLEMENTED();
6275     return false;
6276 }
6277 
ValidateGetTexParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6278 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
6279                                             angle::EntryPoint entryPoint,
6280                                             TextureType target,
6281                                             GLenum pname,
6282                                             GLsizei bufSize,
6283                                             const GLsizei *length,
6284                                             const GLuint *params)
6285 {
6286     UNIMPLEMENTED();
6287     return false;
6288 }
6289 
ValidateTexParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLfloat * params)6290 bool ValidateTexParameterfvRobustANGLE(const Context *context,
6291                                        angle::EntryPoint entryPoint,
6292                                        TextureType target,
6293                                        GLenum pname,
6294                                        GLsizei bufSize,
6295                                        const GLfloat *params)
6296 {
6297     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6298     {
6299         return false;
6300     }
6301 
6302     return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
6303 }
6304 
ValidateTexParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)6305 bool ValidateTexParameterivRobustANGLE(const Context *context,
6306                                        angle::EntryPoint entryPoint,
6307                                        TextureType target,
6308                                        GLenum pname,
6309                                        GLsizei bufSize,
6310                                        const GLint *params)
6311 {
6312     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6313     {
6314         return false;
6315     }
6316 
6317     return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
6318 }
6319 
ValidateTexParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)6320 bool ValidateTexParameterIivRobustANGLE(const Context *context,
6321                                         angle::EntryPoint entryPoint,
6322                                         TextureType target,
6323                                         GLenum pname,
6324                                         GLsizei bufSize,
6325                                         const GLint *params)
6326 {
6327     UNIMPLEMENTED();
6328     return false;
6329 }
6330 
ValidateTexParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLuint * params)6331 bool ValidateTexParameterIuivRobustANGLE(const Context *context,
6332                                          angle::EntryPoint entryPoint,
6333                                          TextureType target,
6334                                          GLenum pname,
6335                                          GLsizei bufSize,
6336                                          const GLuint *params)
6337 {
6338     UNIMPLEMENTED();
6339     return false;
6340 }
6341 
ValidateGetSamplerParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6342 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
6343                                               angle::EntryPoint entryPoint,
6344                                               SamplerID sampler,
6345                                               GLenum pname,
6346                                               GLsizei bufSize,
6347                                               const GLsizei *length,
6348                                               const GLfloat *params)
6349 {
6350     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6351     {
6352         return false;
6353     }
6354 
6355     GLsizei numParams = 0;
6356 
6357     if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
6358     {
6359         return false;
6360     }
6361 
6362     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6363     {
6364         return false;
6365     }
6366 
6367     SetRobustLengthParam(length, numParams);
6368     return true;
6369 }
6370 
ValidateGetSamplerParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6371 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
6372                                               angle::EntryPoint entryPoint,
6373                                               SamplerID sampler,
6374                                               GLenum pname,
6375                                               GLsizei bufSize,
6376                                               const GLsizei *length,
6377                                               const GLint *params)
6378 {
6379     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6380     {
6381         return false;
6382     }
6383 
6384     GLsizei numParams = 0;
6385 
6386     if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
6387     {
6388         return false;
6389     }
6390 
6391     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6392     {
6393         return false;
6394     }
6395 
6396     SetRobustLengthParam(length, numParams);
6397     return true;
6398 }
6399 
ValidateGetSamplerParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6400 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
6401                                                angle::EntryPoint entryPoint,
6402                                                SamplerID sampler,
6403                                                GLenum pname,
6404                                                GLsizei bufSize,
6405                                                const GLsizei *length,
6406                                                const GLint *params)
6407 {
6408     UNIMPLEMENTED();
6409     return false;
6410 }
6411 
ValidateGetSamplerParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6412 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
6413                                                 angle::EntryPoint entryPoint,
6414                                                 SamplerID sampler,
6415                                                 GLenum pname,
6416                                                 GLsizei bufSize,
6417                                                 const GLsizei *length,
6418                                                 const GLuint *params)
6419 {
6420     UNIMPLEMENTED();
6421     return false;
6422 }
6423 
ValidateSamplerParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLfloat * params)6424 bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
6425                                            angle::EntryPoint entryPoint,
6426                                            SamplerID sampler,
6427                                            GLenum pname,
6428                                            GLsizei bufSize,
6429                                            const GLfloat *params)
6430 {
6431     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6432     {
6433         return false;
6434     }
6435 
6436     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
6437 }
6438 
ValidateSamplerParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * params)6439 bool ValidateSamplerParameterivRobustANGLE(const Context *context,
6440                                            angle::EntryPoint entryPoint,
6441                                            SamplerID sampler,
6442                                            GLenum pname,
6443                                            GLsizei bufSize,
6444                                            const GLint *params)
6445 {
6446     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6447     {
6448         return false;
6449     }
6450 
6451     return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
6452 }
6453 
ValidateSamplerParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * param)6454 bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
6455                                             angle::EntryPoint entryPoint,
6456                                             SamplerID sampler,
6457                                             GLenum pname,
6458                                             GLsizei bufSize,
6459                                             const GLint *param)
6460 {
6461     UNIMPLEMENTED();
6462     return false;
6463 }
6464 
ValidateSamplerParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLuint * param)6465 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
6466                                              angle::EntryPoint entryPoint,
6467                                              SamplerID sampler,
6468                                              GLenum pname,
6469                                              GLsizei bufSize,
6470                                              const GLuint *param)
6471 {
6472     UNIMPLEMENTED();
6473     return false;
6474 }
6475 
ValidateGetVertexAttribfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6476 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
6477                                           angle::EntryPoint entryPoint,
6478                                           GLuint index,
6479                                           GLenum pname,
6480                                           GLsizei bufSize,
6481                                           const GLsizei *length,
6482                                           const GLfloat *params)
6483 {
6484     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6485     {
6486         return false;
6487     }
6488 
6489     GLsizei writeLength = 0;
6490 
6491     if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
6492     {
6493         return false;
6494     }
6495 
6496     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6497     {
6498         return false;
6499     }
6500 
6501     SetRobustLengthParam(length, writeLength);
6502     return true;
6503 }
6504 
ValidateGetVertexAttribivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6505 bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
6506                                           angle::EntryPoint entryPoint,
6507                                           GLuint index,
6508                                           GLenum pname,
6509                                           GLsizei bufSize,
6510                                           const GLsizei *length,
6511                                           const GLint *params)
6512 {
6513     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6514     {
6515         return false;
6516     }
6517 
6518     GLsizei writeLength = 0;
6519 
6520     if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
6521     {
6522         return false;
6523     }
6524 
6525     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6526     {
6527         return false;
6528     }
6529 
6530     SetRobustLengthParam(length, writeLength);
6531 
6532     return true;
6533 }
6534 
ValidateGetVertexAttribPointervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * pointer)6535 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
6536                                                 angle::EntryPoint entryPoint,
6537                                                 GLuint index,
6538                                                 GLenum pname,
6539                                                 GLsizei bufSize,
6540                                                 const GLsizei *length,
6541                                                 void *const *pointer)
6542 {
6543     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6544     {
6545         return false;
6546     }
6547 
6548     GLsizei writeLength = 0;
6549 
6550     if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false))
6551     {
6552         return false;
6553     }
6554 
6555     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6556     {
6557         return false;
6558     }
6559 
6560     SetRobustLengthParam(length, writeLength);
6561 
6562     return true;
6563 }
6564 
ValidateGetVertexAttribIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6565 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
6566                                            angle::EntryPoint entryPoint,
6567                                            GLuint index,
6568                                            GLenum pname,
6569                                            GLsizei bufSize,
6570                                            const GLsizei *length,
6571                                            const GLint *params)
6572 {
6573     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6574     {
6575         return false;
6576     }
6577 
6578     GLsizei writeLength = 0;
6579 
6580     if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
6581     {
6582         return false;
6583     }
6584 
6585     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6586     {
6587         return false;
6588     }
6589 
6590     SetRobustLengthParam(length, writeLength);
6591 
6592     return true;
6593 }
6594 
ValidateGetVertexAttribIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6595 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
6596                                             angle::EntryPoint entryPoint,
6597                                             GLuint index,
6598                                             GLenum pname,
6599                                             GLsizei bufSize,
6600                                             const GLsizei *length,
6601                                             const GLuint *params)
6602 {
6603     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6604     {
6605         return false;
6606     }
6607 
6608     GLsizei writeLength = 0;
6609 
6610     if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
6611     {
6612         return false;
6613     }
6614 
6615     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6616     {
6617         return false;
6618     }
6619 
6620     SetRobustLengthParam(length, writeLength);
6621 
6622     return true;
6623 }
6624 
ValidateGetActiveUniformBlockivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6625 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
6626                                                 angle::EntryPoint entryPoint,
6627                                                 ShaderProgramID program,
6628                                                 UniformBlockIndex uniformBlockIndex,
6629                                                 GLenum pname,
6630                                                 GLsizei bufSize,
6631                                                 const GLsizei *length,
6632                                                 const GLint *params)
6633 {
6634     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6635     {
6636         return false;
6637     }
6638 
6639     GLsizei writeLength = 0;
6640 
6641     if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname,
6642                                              &writeLength))
6643     {
6644         return false;
6645     }
6646 
6647     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6648     {
6649         return false;
6650     }
6651 
6652     SetRobustLengthParam(length, writeLength);
6653 
6654     return true;
6655 }
6656 
ValidateGetInternalformativRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6657 bool ValidateGetInternalformativRobustANGLE(const Context *context,
6658                                             angle::EntryPoint entryPoint,
6659                                             GLenum target,
6660                                             GLenum internalformat,
6661                                             GLenum pname,
6662                                             GLsizei bufSize,
6663                                             const GLsizei *length,
6664                                             const GLint *params)
6665 {
6666     if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6667     {
6668         return false;
6669     }
6670 
6671     GLsizei numParams = 0;
6672 
6673     if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
6674                                          bufSize, &numParams))
6675     {
6676         return false;
6677     }
6678 
6679     if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6680     {
6681         return false;
6682     }
6683 
6684     SetRobustLengthParam(length, numParams);
6685 
6686     return true;
6687 }
6688 
6689 // Perform validation from WebGL 2 section 5.10 "Invalid Clears":
6690 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
6691 // specified clear value and the type of a buffer that is being cleared generates an
6692 // INVALID_OPERATION error instead of producing undefined results
ValidateWebGLFramebufferAttachmentClearType(const Context * context,angle::EntryPoint entryPoint,GLint drawbuffer,const GLenum * validComponentTypes,size_t validComponentTypeCount)6693 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
6694                                                  angle::EntryPoint entryPoint,
6695                                                  GLint drawbuffer,
6696                                                  const GLenum *validComponentTypes,
6697                                                  size_t validComponentTypeCount)
6698 {
6699     const FramebufferAttachment *attachment =
6700         context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
6701     if (attachment)
6702     {
6703         GLenum componentType = attachment->getFormat().info->componentType;
6704         const GLenum *end    = validComponentTypes + validComponentTypeCount;
6705         if (std::find(validComponentTypes, end, componentType) == end)
6706         {
6707             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoDefinedClearConversion);
6708             return false;
6709         }
6710     }
6711 
6712     return true;
6713 }
6714 
ValidateRobustCompressedTexImageBase(const Context * context,angle::EntryPoint entryPoint,GLsizei imageSize,GLsizei dataSize)6715 bool ValidateRobustCompressedTexImageBase(const Context *context,
6716                                           angle::EntryPoint entryPoint,
6717                                           GLsizei imageSize,
6718                                           GLsizei dataSize)
6719 {
6720     if (!ValidateRobustEntryPoint(context, entryPoint, dataSize))
6721     {
6722         return false;
6723     }
6724 
6725     Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
6726     if (pixelUnpackBuffer == nullptr)
6727     {
6728         if (dataSize < imageSize)
6729         {
6730             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
6731         }
6732     }
6733     return true;
6734 }
6735 
ValidateGetBufferParameterBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,bool pointerVersion,GLsizei * numParams)6736 bool ValidateGetBufferParameterBase(const Context *context,
6737                                     angle::EntryPoint entryPoint,
6738                                     BufferBinding target,
6739                                     GLenum pname,
6740                                     bool pointerVersion,
6741                                     GLsizei *numParams)
6742 {
6743     if (numParams)
6744     {
6745         *numParams = 0;
6746     }
6747 
6748     if (!context->isValidBufferBinding(target))
6749     {
6750         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
6751         return false;
6752     }
6753 
6754     const Buffer *buffer = context->getState().getTargetBuffer(target);
6755     if (!buffer)
6756     {
6757         // A null buffer means that "0" is bound to the requested buffer target
6758         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
6759         return false;
6760     }
6761 
6762     const Extensions &extensions = context->getExtensions();
6763 
6764     switch (pname)
6765     {
6766         case GL_BUFFER_USAGE:
6767         case GL_BUFFER_SIZE:
6768             break;
6769 
6770         case GL_BUFFER_ACCESS_OES:
6771             if (!extensions.mapbufferOES)
6772             {
6773                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6774                 return false;
6775             }
6776             break;
6777 
6778         case GL_BUFFER_MAPPED:
6779             static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
6780             if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES &&
6781                 !extensions.mapBufferRangeEXT)
6782             {
6783                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6784                 return false;
6785             }
6786             break;
6787 
6788         case GL_BUFFER_MAP_POINTER:
6789             if (!pointerVersion)
6790             {
6791                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMapPointerQuery);
6792                 return false;
6793             }
6794             break;
6795 
6796         case GL_BUFFER_ACCESS_FLAGS:
6797         case GL_BUFFER_MAP_OFFSET:
6798         case GL_BUFFER_MAP_LENGTH:
6799             if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT)
6800             {
6801                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6802                 return false;
6803             }
6804             break;
6805 
6806         case GL_MEMORY_SIZE_ANGLE:
6807             if (!context->getExtensions().memorySizeANGLE)
6808             {
6809                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
6810                 return false;
6811             }
6812             break;
6813 
6814         case GL_RESOURCE_INITIALIZED_ANGLE:
6815             if (!context->getExtensions().robustResourceInitializationANGLE)
6816             {
6817                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
6818                                        kRobustResourceInitializationExtensionRequired);
6819                 return false;
6820             }
6821             break;
6822 
6823         default:
6824             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6825             return false;
6826     }
6827 
6828     // All buffer parameter queries return one value.
6829     if (numParams)
6830     {
6831         *numParams = 1;
6832     }
6833 
6834     return true;
6835 }
6836 
ValidateGetRenderbufferParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLsizei * length)6837 bool ValidateGetRenderbufferParameterivBase(const Context *context,
6838                                             angle::EntryPoint entryPoint,
6839                                             GLenum target,
6840                                             GLenum pname,
6841                                             GLsizei *length)
6842 {
6843     if (length)
6844     {
6845         *length = 0;
6846     }
6847 
6848     if (target != GL_RENDERBUFFER)
6849     {
6850         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
6851         return false;
6852     }
6853 
6854     Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
6855     if (renderbuffer == nullptr)
6856     {
6857         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kRenderbufferNotBound);
6858         return false;
6859     }
6860 
6861     switch (pname)
6862     {
6863         case GL_RENDERBUFFER_WIDTH:
6864         case GL_RENDERBUFFER_HEIGHT:
6865         case GL_RENDERBUFFER_INTERNAL_FORMAT:
6866         case GL_RENDERBUFFER_RED_SIZE:
6867         case GL_RENDERBUFFER_GREEN_SIZE:
6868         case GL_RENDERBUFFER_BLUE_SIZE:
6869         case GL_RENDERBUFFER_ALPHA_SIZE:
6870         case GL_RENDERBUFFER_DEPTH_SIZE:
6871         case GL_RENDERBUFFER_STENCIL_SIZE:
6872             break;
6873 
6874         case GL_RENDERBUFFER_SAMPLES_ANGLE:
6875             if (context->getClientMajorVersion() < 3 &&
6876                 !context->getExtensions().framebufferMultisampleANGLE)
6877             {
6878                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
6879                 return false;
6880             }
6881             break;
6882 
6883         case GL_MEMORY_SIZE_ANGLE:
6884             if (!context->getExtensions().memorySizeANGLE)
6885             {
6886                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
6887                 return false;
6888             }
6889             break;
6890 
6891         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
6892         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
6893             if (!context->getExtensions().getImageANGLE)
6894             {
6895                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
6896                 return false;
6897             }
6898             break;
6899 
6900         case GL_RESOURCE_INITIALIZED_ANGLE:
6901             if (!context->getExtensions().robustResourceInitializationANGLE)
6902             {
6903                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
6904                                        kRobustResourceInitializationExtensionRequired);
6905                 return false;
6906             }
6907             break;
6908 
6909         default:
6910             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6911             return false;
6912     }
6913 
6914     if (length)
6915     {
6916         *length = 1;
6917     }
6918     return true;
6919 }
6920 
ValidateGetShaderivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID shader,GLenum pname,GLsizei * length)6921 bool ValidateGetShaderivBase(const Context *context,
6922                              angle::EntryPoint entryPoint,
6923                              ShaderProgramID shader,
6924                              GLenum pname,
6925                              GLsizei *length)
6926 {
6927     if (length)
6928     {
6929         *length = 0;
6930     }
6931 
6932     if (context->isContextLost())
6933     {
6934         ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
6935 
6936         if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
6937         {
6938             // Generate an error but still return true, the context still needs to return a
6939             // value in this case.
6940             return true;
6941         }
6942         else
6943         {
6944             return false;
6945         }
6946     }
6947 
6948     if (GetValidShader(context, entryPoint, shader) == nullptr)
6949     {
6950         return false;
6951     }
6952 
6953     switch (pname)
6954     {
6955         case GL_SHADER_TYPE:
6956         case GL_DELETE_STATUS:
6957         case GL_COMPILE_STATUS:
6958         case GL_INFO_LOG_LENGTH:
6959         case GL_SHADER_SOURCE_LENGTH:
6960             break;
6961 
6962         case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
6963             if (!context->getExtensions().translatedShaderSourceANGLE)
6964             {
6965                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
6966                 return false;
6967             }
6968             break;
6969 
6970         case GL_COMPLETION_STATUS_KHR:
6971             if (!context->getExtensions().parallelShaderCompileKHR)
6972             {
6973                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
6974                 return false;
6975             }
6976             break;
6977 
6978         default:
6979             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6980             return false;
6981     }
6982 
6983     if (length)
6984     {
6985         *length = 1;
6986     }
6987     return true;
6988 }
6989 
ValidateGetTexParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei * length)6990 bool ValidateGetTexParameterBase(const Context *context,
6991                                  angle::EntryPoint entryPoint,
6992                                  TextureType target,
6993                                  GLenum pname,
6994                                  GLsizei *length)
6995 {
6996     if (length)
6997     {
6998         *length = 0;
6999     }
7000 
7001     if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
7002         target == TextureType::Buffer)
7003     {
7004         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
7005         return false;
7006     }
7007 
7008     if (context->getTextureByType(target) == nullptr)
7009     {
7010         // Should only be possible for external textures
7011         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
7012         return false;
7013     }
7014 
7015     if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
7016     {
7017         ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7018         return false;
7019     }
7020 
7021     switch (pname)
7022     {
7023         case GL_TEXTURE_MAG_FILTER:
7024         case GL_TEXTURE_MIN_FILTER:
7025         case GL_TEXTURE_WRAP_S:
7026         case GL_TEXTURE_WRAP_T:
7027             break;
7028 
7029         case GL_TEXTURE_USAGE_ANGLE:
7030             if (!context->getExtensions().textureUsageANGLE)
7031             {
7032                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7033                 return false;
7034             }
7035             break;
7036 
7037         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
7038             if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
7039             {
7040                 return false;
7041             }
7042             break;
7043 
7044         case GL_TEXTURE_IMMUTABLE_FORMAT:
7045             if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT)
7046             {
7047                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7048                 return false;
7049             }
7050             break;
7051 
7052         case GL_TEXTURE_WRAP_R:
7053         case GL_TEXTURE_IMMUTABLE_LEVELS:
7054         case GL_TEXTURE_SWIZZLE_R:
7055         case GL_TEXTURE_SWIZZLE_G:
7056         case GL_TEXTURE_SWIZZLE_B:
7057         case GL_TEXTURE_SWIZZLE_A:
7058         case GL_TEXTURE_BASE_LEVEL:
7059         case GL_TEXTURE_MAX_LEVEL:
7060         case GL_TEXTURE_MIN_LOD:
7061         case GL_TEXTURE_MAX_LOD:
7062             if (context->getClientMajorVersion() < 3)
7063             {
7064                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
7065                 return false;
7066             }
7067             break;
7068 
7069         case GL_TEXTURE_COMPARE_MODE:
7070         case GL_TEXTURE_COMPARE_FUNC:
7071             if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT)
7072             {
7073                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7074                 return false;
7075             }
7076             break;
7077 
7078         case GL_TEXTURE_SRGB_DECODE_EXT:
7079             if (!context->getExtensions().textureSRGBDecodeEXT)
7080             {
7081                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7082                 return false;
7083             }
7084             break;
7085 
7086         case GL_DEPTH_STENCIL_TEXTURE_MODE:
7087             if (context->getClientVersion() < ES_3_1 &&
7088                 !context->getExtensions().stencilTexturingANGLE)
7089             {
7090                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7091                 return false;
7092             }
7093             break;
7094 
7095         case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
7096             if (context->getClientVersion() < ES_3_1)
7097             {
7098                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
7099                 return false;
7100             }
7101             break;
7102 
7103         case GL_GENERATE_MIPMAP:
7104         case GL_TEXTURE_CROP_RECT_OES:
7105             // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
7106             // after GL_OES_draw_texture functionality implemented
7107             if (context->getClientMajorVersion() > 1)
7108             {
7109                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7110                 return false;
7111             }
7112             break;
7113 
7114         case GL_MEMORY_SIZE_ANGLE:
7115             if (!context->getExtensions().memorySizeANGLE)
7116             {
7117                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7118                 return false;
7119             }
7120             break;
7121 
7122         case GL_TEXTURE_BORDER_COLOR:
7123             if (!context->getExtensions().textureBorderClampAny() &&
7124                 context->getClientVersion() < ES_3_2)
7125             {
7126                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7127                 return false;
7128             }
7129             break;
7130 
7131         case GL_TEXTURE_NATIVE_ID_ANGLE:
7132             if (!context->getExtensions().textureExternalUpdateANGLE)
7133             {
7134                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7135                 return false;
7136             }
7137             break;
7138 
7139         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
7140         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
7141             if (!context->getExtensions().getImageANGLE)
7142             {
7143                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
7144                 return false;
7145             }
7146             break;
7147 
7148         case GL_RESOURCE_INITIALIZED_ANGLE:
7149             if (!context->getExtensions().robustResourceInitializationANGLE)
7150             {
7151                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
7152                                        kRobustResourceInitializationExtensionRequired);
7153                 return false;
7154             }
7155             break;
7156 
7157         case GL_TEXTURE_PROTECTED_EXT:
7158             if (!context->getExtensions().protectedTexturesEXT)
7159             {
7160                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
7161                 return false;
7162             }
7163             break;
7164 
7165         case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
7166             break;
7167 
7168         default:
7169             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7170             return false;
7171     }
7172 
7173     if (length)
7174     {
7175         *length = GetTexParameterCount(pname);
7176     }
7177     return true;
7178 }
7179 
ValidateGetVertexAttribBase(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei * length,bool pointer,bool pureIntegerEntryPoint)7180 bool ValidateGetVertexAttribBase(const Context *context,
7181                                  angle::EntryPoint entryPoint,
7182                                  GLuint index,
7183                                  GLenum pname,
7184                                  GLsizei *length,
7185                                  bool pointer,
7186                                  bool pureIntegerEntryPoint)
7187 {
7188     if (length)
7189     {
7190         *length = 0;
7191     }
7192 
7193     if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
7194     {
7195         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
7196         return false;
7197     }
7198 
7199     if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
7200     {
7201         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
7202         return false;
7203     }
7204 
7205     if (pointer)
7206     {
7207         if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
7208         {
7209             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7210             return false;
7211         }
7212     }
7213     else
7214     {
7215         switch (pname)
7216         {
7217             case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7218             case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7219             case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7220             case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7221             case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7222             case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7223             case GL_CURRENT_VERTEX_ATTRIB:
7224                 break;
7225 
7226             case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7227                 static_assert(
7228                     GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
7229                     "ANGLE extension enums not equal to GL enums.");
7230                 if (context->getClientMajorVersion() < 3 &&
7231                     !context->getExtensions().instancedArraysAny())
7232                 {
7233                     ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7234                     return false;
7235                 }
7236                 break;
7237 
7238             case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7239                 if (context->getClientMajorVersion() < 3)
7240                 {
7241                     ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7242                     return false;
7243                 }
7244                 break;
7245 
7246             case GL_VERTEX_ATTRIB_BINDING:
7247             case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
7248                 if (context->getClientVersion() < ES_3_1)
7249                 {
7250                     ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
7251                     return false;
7252                 }
7253                 break;
7254 
7255             default:
7256                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7257                 return false;
7258         }
7259     }
7260 
7261     if (length)
7262     {
7263         if (pname == GL_CURRENT_VERTEX_ATTRIB)
7264         {
7265             *length = 4;
7266         }
7267         else
7268         {
7269             *length = 1;
7270         }
7271     }
7272 
7273     return true;
7274 }
7275 
ValidatePixelPack(const Context * context,angle::EntryPoint entryPoint,GLenum format,GLenum type,GLint x,GLint y,GLsizei width,GLsizei height,GLsizei bufSize,GLsizei * length,const void * pixels)7276 bool ValidatePixelPack(const Context *context,
7277                        angle::EntryPoint entryPoint,
7278                        GLenum format,
7279                        GLenum type,
7280                        GLint x,
7281                        GLint y,
7282                        GLsizei width,
7283                        GLsizei height,
7284                        GLsizei bufSize,
7285                        GLsizei *length,
7286                        const void *pixels)
7287 {
7288     // Check for pixel pack buffer related API errors
7289     Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
7290     if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
7291     {
7292         // ...the buffer object's data store is currently mapped.
7293         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
7294         return false;
7295     }
7296     if (pixelPackBuffer != nullptr &&
7297         pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
7298     {
7299         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
7300         return false;
7301     }
7302 
7303     // ..  the data would be packed to the buffer object such that the memory writes required
7304     // would exceed the data store size.
7305     const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
7306     const Extents size(width, height, 1);
7307     const auto &pack = context->getState().getPackState();
7308 
7309     GLuint endByte = 0;
7310     if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
7311     {
7312         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7313         return false;
7314     }
7315 
7316     if (bufSize >= 0)
7317     {
7318         if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
7319         {
7320             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
7321             return false;
7322         }
7323     }
7324 
7325     if (pixelPackBuffer != nullptr)
7326     {
7327         CheckedNumeric<size_t> checkedEndByte(endByte);
7328         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
7329         checkedEndByte += checkedOffset;
7330 
7331         if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
7332         {
7333             // Overflow past the end of the buffer
7334             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kParamOverflow);
7335             return false;
7336         }
7337     }
7338 
7339     if (pixelPackBuffer == nullptr && length != nullptr)
7340     {
7341         if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
7342         {
7343             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7344             return false;
7345         }
7346 
7347         *length = static_cast<GLsizei>(endByte);
7348     }
7349 
7350     if (context->isWebGL())
7351     {
7352         // WebGL 2.0 disallows the scenario:
7353         //   GL_PACK_SKIP_PIXELS + width > DataStoreWidth
7354         // where:
7355         //   DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width)
7356         // Since these two pack parameters can only be set to non-zero values
7357         // on WebGL 2.0 contexts, verify them for all WebGL contexts.
7358         GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width;
7359         if (pack.skipPixels + width > dataStoreWidth)
7360         {
7361             ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidPackParametersForWebGL);
7362             return false;
7363         }
7364     }
7365 
7366     return true;
7367 }
7368 
ValidateReadPixelsBase(const Context * context,angle::EntryPoint entryPoint,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,const void * pixels)7369 bool ValidateReadPixelsBase(const Context *context,
7370                             angle::EntryPoint entryPoint,
7371                             GLint x,
7372                             GLint y,
7373                             GLsizei width,
7374                             GLsizei height,
7375                             GLenum format,
7376                             GLenum type,
7377                             GLsizei bufSize,
7378                             GLsizei *length,
7379                             GLsizei *columns,
7380                             GLsizei *rows,
7381                             const void *pixels)
7382 {
7383     if (length != nullptr)
7384     {
7385         *length = 0;
7386     }
7387     if (rows != nullptr)
7388     {
7389         *rows = 0;
7390     }
7391     if (columns != nullptr)
7392     {
7393         *columns = 0;
7394     }
7395 
7396     if (width < 0 || height < 0)
7397     {
7398         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
7399         return false;
7400     }
7401 
7402     Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
7403     ASSERT(readFramebuffer);
7404 
7405     if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
7406     {
7407         return false;
7408     }
7409 
7410     // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
7411     // resolved before reading.
7412     if (!readFramebuffer->isDefault() &&
7413         !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
7414     {
7415         return false;
7416     }
7417 
7418     if (readFramebuffer->getReadBufferState() == GL_NONE)
7419     {
7420         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
7421         return false;
7422     }
7423 
7424     const FramebufferAttachment *readBuffer = nullptr;
7425     switch (format)
7426     {
7427         case GL_DEPTH_COMPONENT:
7428             readBuffer = readFramebuffer->getDepthAttachment();
7429             break;
7430         case GL_STENCIL_INDEX_OES:
7431         case GL_DEPTH_STENCIL_OES:
7432             readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
7433             break;
7434         default:
7435             readBuffer = readFramebuffer->getReadColorAttachment();
7436             break;
7437     }
7438 
7439     // OVR_multiview2, Revision 1:
7440     // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
7441     // the number of views in the current read framebuffer is more than one.
7442     if (readFramebuffer->readDisallowedByMultiview())
7443     {
7444         ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
7445         return false;
7446     }
7447 
7448     if (context->isWebGL())
7449     {
7450         // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
7451         // excluding formats LUMINANCE and LUMINANCE_ALPHA.".  This requires validating the format
7452         // and type before validating the combination of format and type.  However, the
7453         // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
7454         // verifies that GL_INVALID_OPERATION is generated.
7455         // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
7456         // dEQP/WebGL.
7457         if (!ValidReadPixelsFormatEnum(context, format))
7458         {
7459             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
7460             return false;
7461         }
7462 
7463         if (!ValidReadPixelsTypeEnum(context, type))
7464         {
7465             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
7466             return false;
7467         }
7468     }
7469 
7470     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
7471     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
7472     // attachment and WebGL defines it to be an error. We do the check unconditionally as the
7473     // situation is an application error that would lead to a crash in ANGLE.
7474     if (readBuffer == nullptr)
7475     {
7476         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
7477         return false;
7478     }
7479 
7480     GLenum currentFormat = GL_NONE;
7481     GLenum currentType   = GL_NONE;
7482 
7483     switch (format)
7484     {
7485         case GL_DEPTH_COMPONENT:
7486         case GL_STENCIL_INDEX_OES:
7487         case GL_DEPTH_STENCIL_OES:
7488             // Only rely on ValidReadPixelsFormatType for depth/stencil formats
7489             break;
7490         default:
7491             currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
7492             currentType   = readFramebuffer->getImplementationColorReadType(context);
7493             break;
7494     }
7495 
7496     bool validFormatTypeCombination =
7497         ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
7498 
7499     if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
7500     {
7501         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
7502         return false;
7503     }
7504 
7505     if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length,
7506                            pixels))
7507     {
7508         return false;
7509     }
7510 
7511     auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
7512         angle::CheckedNumeric<int> clippedExtent(length);
7513         if (start < 0)
7514         {
7515             // "subtract" the area that is less than 0
7516             clippedExtent += start;
7517         }
7518 
7519         angle::CheckedNumeric<int> readExtent = start;
7520         readExtent += length;
7521         if (!readExtent.IsValid())
7522         {
7523             return false;
7524         }
7525 
7526         if (readExtent.ValueOrDie() > bufferSize)
7527         {
7528             // Subtract the region to the right of the read buffer
7529             clippedExtent -= (readExtent - bufferSize);
7530         }
7531 
7532         if (!clippedExtent.IsValid())
7533         {
7534             return false;
7535         }
7536 
7537         *outExtent = std::max<int>(clippedExtent.ValueOrDie(), 0);
7538         return true;
7539     };
7540 
7541     GLsizei writtenColumns = 0;
7542     if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
7543     {
7544         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7545         return false;
7546     }
7547 
7548     GLsizei writtenRows = 0;
7549     if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
7550     {
7551         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7552         return false;
7553     }
7554 
7555     if (columns != nullptr)
7556     {
7557         *columns = writtenColumns;
7558     }
7559 
7560     if (rows != nullptr)
7561     {
7562         *rows = writtenRows;
7563     }
7564 
7565     return true;
7566 }
7567 
7568 template <typename ParamType>
ValidateTexParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)7569 bool ValidateTexParameterBase(const Context *context,
7570                               angle::EntryPoint entryPoint,
7571                               TextureType target,
7572                               GLenum pname,
7573                               GLsizei bufSize,
7574                               bool vectorParams,
7575                               const ParamType *params)
7576 {
7577     if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
7578         target == TextureType::Buffer)
7579     {
7580         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
7581         return false;
7582     }
7583 
7584     if (context->getTextureByType(target) == nullptr)
7585     {
7586         // Should only be possible for external textures
7587         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
7588         return false;
7589     }
7590 
7591     const GLsizei minBufSize = GetTexParameterCount(pname);
7592     if (bufSize >= 0 && bufSize < minBufSize)
7593     {
7594         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
7595         return false;
7596     }
7597 
7598     if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
7599     {
7600         ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7601         return false;
7602     }
7603 
7604     switch (pname)
7605     {
7606         case GL_TEXTURE_WRAP_R:
7607         case GL_TEXTURE_SWIZZLE_R:
7608         case GL_TEXTURE_SWIZZLE_G:
7609         case GL_TEXTURE_SWIZZLE_B:
7610         case GL_TEXTURE_SWIZZLE_A:
7611         case GL_TEXTURE_BASE_LEVEL:
7612         case GL_TEXTURE_MAX_LEVEL:
7613         case GL_TEXTURE_COMPARE_MODE:
7614         case GL_TEXTURE_COMPARE_FUNC:
7615         case GL_TEXTURE_MIN_LOD:
7616         case GL_TEXTURE_MAX_LOD:
7617             if (context->getClientMajorVersion() < 3 &&
7618                 !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
7619             {
7620                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
7621                 return false;
7622             }
7623             if (target == TextureType::External &&
7624                 !context->getExtensions().EGLImageExternalEssl3OES)
7625             {
7626                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7627                 return false;
7628             }
7629             if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL)
7630             {
7631                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7632             }
7633             break;
7634 
7635         case GL_GENERATE_MIPMAP:
7636         case GL_TEXTURE_CROP_RECT_OES:
7637             if (context->getClientMajorVersion() > 1)
7638             {
7639                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7640                 return false;
7641             }
7642             break;
7643 
7644         default:
7645             break;
7646     }
7647 
7648     if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
7649     {
7650         switch (pname)
7651         {
7652             case GL_TEXTURE_MIN_FILTER:
7653             case GL_TEXTURE_MAG_FILTER:
7654             case GL_TEXTURE_WRAP_S:
7655             case GL_TEXTURE_WRAP_T:
7656             case GL_TEXTURE_WRAP_R:
7657             case GL_TEXTURE_MIN_LOD:
7658             case GL_TEXTURE_MAX_LOD:
7659             case GL_TEXTURE_COMPARE_MODE:
7660             case GL_TEXTURE_COMPARE_FUNC:
7661             case GL_TEXTURE_BORDER_COLOR:
7662                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
7663                 return false;
7664         }
7665     }
7666 
7667     switch (pname)
7668     {
7669         case GL_TEXTURE_WRAP_S:
7670         case GL_TEXTURE_WRAP_T:
7671         case GL_TEXTURE_WRAP_R:
7672         {
7673             bool restrictedWrapModes = ((target == TextureType::External &&
7674                                          !context->getExtensions().EGLImageExternalWrapModesEXT) ||
7675                                         target == TextureType::Rectangle);
7676             if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes))
7677             {
7678                 return false;
7679             }
7680         }
7681         break;
7682 
7683         case GL_TEXTURE_MIN_FILTER:
7684         {
7685             bool restrictedMinFilter =
7686                 target == TextureType::External || target == TextureType::Rectangle;
7687             if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter))
7688             {
7689                 return false;
7690             }
7691         }
7692         break;
7693 
7694         case GL_TEXTURE_MAG_FILTER:
7695             if (!ValidateTextureMagFilterValue(context, entryPoint, params))
7696             {
7697                 return false;
7698             }
7699             break;
7700 
7701         case GL_TEXTURE_USAGE_ANGLE:
7702             if (!context->getExtensions().textureUsageANGLE)
7703             {
7704                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7705                 return false;
7706             }
7707 
7708             switch (ConvertToGLenum(params[0]))
7709             {
7710                 case GL_NONE:
7711                 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
7712                     break;
7713 
7714                 default:
7715                     ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7716                     return false;
7717             }
7718             break;
7719 
7720         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
7721         {
7722             GLfloat paramValue = static_cast<GLfloat>(params[0]);
7723             if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
7724             {
7725                 return false;
7726             }
7727             ASSERT(static_cast<ParamType>(paramValue) == params[0]);
7728         }
7729         break;
7730 
7731         case GL_TEXTURE_MIN_LOD:
7732         case GL_TEXTURE_MAX_LOD:
7733             // any value is permissible
7734             break;
7735 
7736         case GL_TEXTURE_COMPARE_MODE:
7737             if (!ValidateTextureCompareModeValue(context, entryPoint, params))
7738             {
7739                 return false;
7740             }
7741             break;
7742 
7743         case GL_TEXTURE_COMPARE_FUNC:
7744             if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
7745             {
7746                 return false;
7747             }
7748             break;
7749 
7750         case GL_TEXTURE_SWIZZLE_R:
7751         case GL_TEXTURE_SWIZZLE_G:
7752         case GL_TEXTURE_SWIZZLE_B:
7753         case GL_TEXTURE_SWIZZLE_A:
7754             switch (ConvertToGLenum(params[0]))
7755             {
7756                 case GL_RED:
7757                 case GL_GREEN:
7758                 case GL_BLUE:
7759                 case GL_ALPHA:
7760                 case GL_ZERO:
7761                 case GL_ONE:
7762                     break;
7763 
7764                 default:
7765                     ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7766                     return false;
7767             }
7768             break;
7769 
7770         case GL_TEXTURE_BASE_LEVEL:
7771             if (ConvertToGLint(params[0]) < 0)
7772             {
7773                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBaseLevelNegative);
7774                 return false;
7775             }
7776             if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
7777             {
7778                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7779                 return false;
7780             }
7781             if ((target == TextureType::_2DMultisample ||
7782                  target == TextureType::_2DMultisampleArray) &&
7783                 static_cast<GLuint>(params[0]) != 0)
7784             {
7785                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7786                 return false;
7787             }
7788             if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
7789             {
7790                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7791                 return false;
7792             }
7793             break;
7794 
7795         case GL_TEXTURE_MAX_LEVEL:
7796             if (ConvertToGLint(params[0]) < 0)
7797             {
7798                 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
7799                 return false;
7800             }
7801             break;
7802 
7803         case GL_DEPTH_STENCIL_TEXTURE_MODE:
7804             if (context->getClientVersion() < ES_3_1 &&
7805                 !context->getExtensions().stencilTexturingANGLE)
7806             {
7807                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7808                 return false;
7809             }
7810             switch (ConvertToGLenum(params[0]))
7811             {
7812                 case GL_DEPTH_COMPONENT:
7813                 case GL_STENCIL_INDEX:
7814                     break;
7815 
7816                 default:
7817                     ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7818                     return false;
7819             }
7820             break;
7821 
7822         case GL_TEXTURE_SRGB_DECODE_EXT:
7823             if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
7824             {
7825                 return false;
7826             }
7827             break;
7828 
7829         case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
7830             if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params))
7831             {
7832                 return false;
7833             }
7834             break;
7835 
7836         case GL_GENERATE_MIPMAP:
7837             if (context->getClientMajorVersion() > 1)
7838             {
7839                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7840                 return false;
7841             }
7842             break;
7843 
7844         case GL_TEXTURE_CROP_RECT_OES:
7845             if (context->getClientMajorVersion() > 1)
7846             {
7847                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7848                 return false;
7849             }
7850             if (!vectorParams)
7851             {
7852                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
7853                 return false;
7854             }
7855             break;
7856 
7857         case GL_TEXTURE_BORDER_COLOR:
7858             if (!context->getExtensions().textureBorderClampAny() &&
7859                 context->getClientVersion() < ES_3_2)
7860             {
7861                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7862                 return false;
7863             }
7864             if (!vectorParams)
7865             {
7866                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
7867                 return false;
7868             }
7869             break;
7870 
7871         case GL_RESOURCE_INITIALIZED_ANGLE:
7872             if (!context->getExtensions().robustResourceInitializationANGLE)
7873             {
7874                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
7875                                        kRobustResourceInitializationExtensionRequired);
7876                 return false;
7877             }
7878             break;
7879 
7880         case GL_TEXTURE_PROTECTED_EXT:
7881             if (!context->getExtensions().protectedTexturesEXT)
7882             {
7883                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
7884                 return false;
7885             }
7886             if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
7887             {
7888                 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
7889                                        "Protected Texture must match Protected Context");
7890                 return false;
7891             }
7892             break;
7893 
7894         case GL_RENDERABILITY_VALIDATION_ANGLE:
7895             if (!context->getExtensions().renderabilityValidationANGLE)
7896             {
7897                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7898                 return false;
7899             }
7900             break;
7901 
7902         default:
7903             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7904             return false;
7905     }
7906 
7907     return true;
7908 }
7909 
7910 template bool ValidateTexParameterBase(const Context *,
7911                                        angle::EntryPoint,
7912                                        TextureType,
7913                                        GLenum,
7914                                        GLsizei,
7915                                        bool,
7916                                        const GLfloat *);
7917 template bool ValidateTexParameterBase(const Context *,
7918                                        angle::EntryPoint,
7919                                        TextureType,
7920                                        GLenum,
7921                                        GLsizei,
7922                                        bool,
7923                                        const GLint *);
7924 template bool ValidateTexParameterBase(const Context *,
7925                                        angle::EntryPoint,
7926                                        TextureType,
7927                                        GLenum,
7928                                        GLsizei,
7929                                        bool,
7930                                        const GLuint *);
7931 
ValidateGetActiveUniformBlockivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,GLsizei * length)7932 bool ValidateGetActiveUniformBlockivBase(const Context *context,
7933                                          angle::EntryPoint entryPoint,
7934                                          ShaderProgramID program,
7935                                          UniformBlockIndex uniformBlockIndex,
7936                                          GLenum pname,
7937                                          GLsizei *length)
7938 {
7939     if (length)
7940     {
7941         *length = 0;
7942     }
7943 
7944     if (context->getClientMajorVersion() < 3)
7945     {
7946         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
7947         return false;
7948     }
7949 
7950     Program *programObject = GetValidProgram(context, entryPoint, program);
7951     if (!programObject)
7952     {
7953         return false;
7954     }
7955 
7956     if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
7957     {
7958         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
7959         return false;
7960     }
7961 
7962     switch (pname)
7963     {
7964         case GL_UNIFORM_BLOCK_BINDING:
7965         case GL_UNIFORM_BLOCK_DATA_SIZE:
7966         case GL_UNIFORM_BLOCK_NAME_LENGTH:
7967         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
7968         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
7969         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
7970         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
7971             break;
7972 
7973         default:
7974             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7975             return false;
7976     }
7977 
7978     if (length)
7979     {
7980         if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
7981         {
7982             const InterfaceBlock &uniformBlock =
7983                 programObject->getUniformBlockByIndex(uniformBlockIndex.value);
7984             *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
7985         }
7986         else
7987         {
7988             *length = 1;
7989         }
7990     }
7991 
7992     return true;
7993 }
7994 
7995 template <typename ParamType>
ValidateSamplerParameterBase(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)7996 bool ValidateSamplerParameterBase(const Context *context,
7997                                   angle::EntryPoint entryPoint,
7998                                   SamplerID sampler,
7999                                   GLenum pname,
8000                                   GLsizei bufSize,
8001                                   bool vectorParams,
8002                                   const ParamType *params)
8003 {
8004     if (context->getClientMajorVersion() < 3)
8005     {
8006         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8007         return false;
8008     }
8009 
8010     if (!context->isSampler(sampler))
8011     {
8012         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
8013         return false;
8014     }
8015 
8016     const GLsizei minBufSize = GetSamplerParameterCount(pname);
8017     if (bufSize >= 0 && bufSize < minBufSize)
8018     {
8019         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
8020         return false;
8021     }
8022 
8023     switch (pname)
8024     {
8025         case GL_TEXTURE_WRAP_S:
8026         case GL_TEXTURE_WRAP_T:
8027         case GL_TEXTURE_WRAP_R:
8028             if (!ValidateTextureWrapModeValue(context, entryPoint, params, false))
8029             {
8030                 return false;
8031             }
8032             break;
8033 
8034         case GL_TEXTURE_MIN_FILTER:
8035             if (!ValidateTextureMinFilterValue(context, entryPoint, params, false))
8036             {
8037                 return false;
8038             }
8039             break;
8040 
8041         case GL_TEXTURE_MAG_FILTER:
8042             if (!ValidateTextureMagFilterValue(context, entryPoint, params))
8043             {
8044                 return false;
8045             }
8046             break;
8047 
8048         case GL_TEXTURE_MIN_LOD:
8049         case GL_TEXTURE_MAX_LOD:
8050             // any value is permissible
8051             break;
8052 
8053         case GL_TEXTURE_COMPARE_MODE:
8054             if (!ValidateTextureCompareModeValue(context, entryPoint, params))
8055             {
8056                 return false;
8057             }
8058             break;
8059 
8060         case GL_TEXTURE_COMPARE_FUNC:
8061             if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
8062             {
8063                 return false;
8064             }
8065             break;
8066 
8067         case GL_TEXTURE_SRGB_DECODE_EXT:
8068             if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
8069             {
8070                 return false;
8071             }
8072             break;
8073 
8074         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
8075         {
8076             GLfloat paramValue = static_cast<GLfloat>(params[0]);
8077             if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
8078             {
8079                 return false;
8080             }
8081         }
8082         break;
8083 
8084         case GL_TEXTURE_BORDER_COLOR:
8085             if (!context->getExtensions().textureBorderClampAny() &&
8086                 context->getClientVersion() < ES_3_2)
8087             {
8088                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
8089                 return false;
8090             }
8091             if (!vectorParams)
8092             {
8093                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
8094                 return false;
8095             }
8096             break;
8097 
8098         default:
8099             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8100             return false;
8101     }
8102 
8103     return true;
8104 }
8105 
8106 template bool ValidateSamplerParameterBase(const Context *,
8107                                            angle::EntryPoint,
8108                                            SamplerID,
8109                                            GLenum,
8110                                            GLsizei,
8111                                            bool,
8112                                            const GLfloat *);
8113 template bool ValidateSamplerParameterBase(const Context *,
8114                                            angle::EntryPoint,
8115                                            SamplerID,
8116                                            GLenum,
8117                                            GLsizei,
8118                                            bool,
8119                                            const GLint *);
8120 template bool ValidateSamplerParameterBase(const Context *,
8121                                            angle::EntryPoint,
8122                                            SamplerID,
8123                                            GLenum,
8124                                            GLsizei,
8125                                            bool,
8126                                            const GLuint *);
8127 
ValidateGetSamplerParameterBase(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei * length)8128 bool ValidateGetSamplerParameterBase(const Context *context,
8129                                      angle::EntryPoint entryPoint,
8130                                      SamplerID sampler,
8131                                      GLenum pname,
8132                                      GLsizei *length)
8133 {
8134     if (length)
8135     {
8136         *length = 0;
8137     }
8138 
8139     if (context->getClientMajorVersion() < 3)
8140     {
8141         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8142         return false;
8143     }
8144 
8145     if (!context->isSampler(sampler))
8146     {
8147         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
8148         return false;
8149     }
8150 
8151     switch (pname)
8152     {
8153         case GL_TEXTURE_WRAP_S:
8154         case GL_TEXTURE_WRAP_T:
8155         case GL_TEXTURE_WRAP_R:
8156         case GL_TEXTURE_MIN_FILTER:
8157         case GL_TEXTURE_MAG_FILTER:
8158         case GL_TEXTURE_MIN_LOD:
8159         case GL_TEXTURE_MAX_LOD:
8160         case GL_TEXTURE_COMPARE_MODE:
8161         case GL_TEXTURE_COMPARE_FUNC:
8162             break;
8163 
8164         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
8165             if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
8166             {
8167                 return false;
8168             }
8169             break;
8170 
8171         case GL_TEXTURE_SRGB_DECODE_EXT:
8172             if (!context->getExtensions().textureSRGBDecodeEXT)
8173             {
8174                 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8175                 return false;
8176             }
8177             break;
8178 
8179         case GL_TEXTURE_BORDER_COLOR:
8180             if (!context->getExtensions().textureBorderClampAny() &&
8181                 context->getClientVersion() < ES_3_2)
8182             {
8183                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
8184                 return false;
8185             }
8186             break;
8187 
8188         default:
8189             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8190             return false;
8191     }
8192 
8193     if (length)
8194     {
8195         *length = GetSamplerParameterCount(pname);
8196     }
8197     return true;
8198 }
8199 
ValidateGetInternalFormativBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * numParams)8200 bool ValidateGetInternalFormativBase(const Context *context,
8201                                      angle::EntryPoint entryPoint,
8202                                      GLenum target,
8203                                      GLenum internalformat,
8204                                      GLenum pname,
8205                                      GLsizei bufSize,
8206                                      GLsizei *numParams)
8207 {
8208     if (numParams)
8209     {
8210         *numParams = 0;
8211     }
8212 
8213     if (context->getClientMajorVersion() < 3)
8214     {
8215         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8216         return false;
8217     }
8218 
8219     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
8220     if (!formatCaps.renderbuffer)
8221     {
8222         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFormatNotRenderable);
8223         return false;
8224     }
8225 
8226     switch (target)
8227     {
8228         case GL_RENDERBUFFER:
8229             break;
8230 
8231         case GL_TEXTURE_2D_MULTISAMPLE:
8232             if (context->getClientVersion() < ES_3_1 &&
8233                 !context->getExtensions().textureMultisampleANGLE)
8234             {
8235                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
8236                 return false;
8237             }
8238             break;
8239         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
8240             if (!context->getExtensions().textureStorageMultisample2dArrayOES)
8241             {
8242                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
8243                 return false;
8244             }
8245             break;
8246         default:
8247             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8248             return false;
8249     }
8250 
8251     if (bufSize < 0)
8252     {
8253         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInsufficientBufferSize);
8254         return false;
8255     }
8256 
8257     GLsizei maxWriteParams = 0;
8258     switch (pname)
8259     {
8260         case GL_NUM_SAMPLE_COUNTS:
8261             maxWriteParams = 1;
8262             break;
8263 
8264         case GL_SAMPLES:
8265             maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
8266             break;
8267 
8268         default:
8269             ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8270             return false;
8271     }
8272 
8273     if (numParams)
8274     {
8275         // glGetInternalFormativ will not overflow bufSize
8276         *numParams = std::min(bufSize, maxWriteParams);
8277     }
8278 
8279     return true;
8280 }
8281 
ValidateFramebufferNotMultisampled(const Context * context,angle::EntryPoint entryPoint,const Framebuffer * framebuffer,bool checkReadBufferResourceSamples)8282 bool ValidateFramebufferNotMultisampled(const Context *context,
8283                                         angle::EntryPoint entryPoint,
8284                                         const Framebuffer *framebuffer,
8285                                         bool checkReadBufferResourceSamples)
8286 {
8287     int samples = checkReadBufferResourceSamples
8288                       ? framebuffer->getReadBufferResourceSamples(context)
8289                       : framebuffer->getSamples(context);
8290     if (samples != 0)
8291     {
8292         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
8293         return false;
8294     }
8295     return true;
8296 }
8297 
ValidateMultitextureUnit(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLenum texture)8298 bool ValidateMultitextureUnit(const PrivateState &state,
8299                               ErrorSet *errors,
8300                               angle::EntryPoint entryPoint,
8301                               GLenum texture)
8302 {
8303     if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + state.getCaps().maxMultitextureUnits)
8304     {
8305         errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit);
8306         return false;
8307     }
8308     return true;
8309 }
8310 
ValidateTexStorageMultisample(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)8311 bool ValidateTexStorageMultisample(const Context *context,
8312                                    angle::EntryPoint entryPoint,
8313                                    TextureType target,
8314                                    GLsizei samples,
8315                                    GLint internalFormat,
8316                                    GLsizei width,
8317                                    GLsizei height)
8318 {
8319     const Caps &caps = context->getCaps();
8320     if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
8321     {
8322         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
8323         return false;
8324     }
8325 
8326     if (samples == 0)
8327     {
8328         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesZero);
8329         return false;
8330     }
8331 
8332     const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
8333     if (!formatCaps.textureAttachment)
8334     {
8335         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRenderableInternalFormat);
8336         return false;
8337     }
8338 
8339     // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
8340     // is one of the unsized base internalformats listed in table 8.11.
8341     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
8342     if (formatInfo.internalFormat == GL_NONE)
8343     {
8344         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
8345         return false;
8346     }
8347 
8348     if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
8349     {
8350         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
8351         return false;
8352     }
8353 
8354     Texture *texture = context->getTextureByType(target);
8355     if (!texture || texture->id().value == 0)
8356     {
8357         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kZeroBoundToTarget);
8358         return false;
8359     }
8360 
8361     if (texture->getImmutableFormat())
8362     {
8363         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImmutableTextureBound);
8364         return false;
8365     }
8366     return true;
8367 }
8368 
ValidateTexStorage2DMultisampleBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)8369 bool ValidateTexStorage2DMultisampleBase(const Context *context,
8370                                          angle::EntryPoint entryPoint,
8371                                          TextureType target,
8372                                          GLsizei samples,
8373                                          GLint internalFormat,
8374                                          GLsizei width,
8375                                          GLsizei height)
8376 {
8377     if (target != TextureType::_2DMultisample)
8378     {
8379         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8380         return false;
8381     }
8382 
8383     if (width < 1 || height < 1)
8384     {
8385         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
8386         return false;
8387     }
8388 
8389     return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat,
8390                                          width, height);
8391 }
8392 
ValidateGetTexLevelParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,GLsizei * length)8393 bool ValidateGetTexLevelParameterBase(const Context *context,
8394                                       angle::EntryPoint entryPoint,
8395                                       TextureTarget target,
8396                                       GLint level,
8397                                       GLenum pname,
8398                                       GLsizei *length)
8399 {
8400 
8401     if (length)
8402     {
8403         *length = 0;
8404     }
8405 
8406     TextureType type = TextureTargetToType(target);
8407 
8408     if (!ValidTexLevelDestinationTarget(context, type))
8409     {
8410         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8411         return false;
8412     }
8413 
8414     if (context->getTextureByType(type) == nullptr)
8415     {
8416         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
8417         return false;
8418     }
8419 
8420     if (!ValidMipLevel(context, type, level))
8421     {
8422         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
8423         return false;
8424     }
8425 
8426     switch (pname)
8427     {
8428         case GL_TEXTURE_RED_TYPE:
8429         case GL_TEXTURE_GREEN_TYPE:
8430         case GL_TEXTURE_BLUE_TYPE:
8431         case GL_TEXTURE_ALPHA_TYPE:
8432         case GL_TEXTURE_DEPTH_TYPE:
8433         case GL_TEXTURE_RED_SIZE:
8434         case GL_TEXTURE_GREEN_SIZE:
8435         case GL_TEXTURE_BLUE_SIZE:
8436         case GL_TEXTURE_ALPHA_SIZE:
8437         case GL_TEXTURE_DEPTH_SIZE:
8438         case GL_TEXTURE_STENCIL_SIZE:
8439         case GL_TEXTURE_SHARED_SIZE:
8440         case GL_TEXTURE_INTERNAL_FORMAT:
8441         case GL_TEXTURE_WIDTH:
8442         case GL_TEXTURE_HEIGHT:
8443         case GL_TEXTURE_DEPTH:
8444         case GL_TEXTURE_SAMPLES:
8445         case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
8446         case GL_TEXTURE_COMPRESSED:
8447             break;
8448 
8449         case GL_RESOURCE_INITIALIZED_ANGLE:
8450             if (!context->getExtensions().robustResourceInitializationANGLE)
8451             {
8452                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
8453                                        kRobustResourceInitializationExtensionRequired);
8454                 return false;
8455             }
8456             break;
8457 
8458         case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
8459         case GL_TEXTURE_BUFFER_OFFSET:
8460         case GL_TEXTURE_BUFFER_SIZE:
8461             if (context->getClientVersion() < Version(3, 2) &&
8462                 !context->getExtensions().textureBufferAny())
8463             {
8464                 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
8465                 return false;
8466             }
8467             break;
8468 
8469         default:
8470             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
8471             return false;
8472     }
8473 
8474     if (length)
8475     {
8476         *length = 1;
8477     }
8478     return true;
8479 }
8480 
ValidateGetMultisamplefvBase(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,const GLfloat * val)8481 bool ValidateGetMultisamplefvBase(const Context *context,
8482                                   angle::EntryPoint entryPoint,
8483                                   GLenum pname,
8484                                   GLuint index,
8485                                   const GLfloat *val)
8486 {
8487     if (pname != GL_SAMPLE_POSITION)
8488     {
8489         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
8490         return false;
8491     }
8492 
8493     Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
8494     GLint samples            = framebuffer->getSamples(context);
8495 
8496     if (index >= static_cast<GLuint>(samples))
8497     {
8498         ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsSamples);
8499         return false;
8500     }
8501 
8502     return true;
8503 }
8504 
ValidateSampleMaskiBase(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint maskNumber,GLbitfield mask)8505 bool ValidateSampleMaskiBase(const PrivateState &state,
8506                              ErrorSet *errors,
8507                              angle::EntryPoint entryPoint,
8508                              GLuint maskNumber,
8509                              GLbitfield mask)
8510 {
8511     if (maskNumber >= static_cast<GLuint>(state.getCaps().maxSampleMaskWords))
8512     {
8513         errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
8514         return false;
8515     }
8516 
8517     return true;
8518 }
8519 
RecordDrawAttribsError(const Context * context,angle::EntryPoint entryPoint)8520 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint)
8521 {
8522     // An overflow can happen when adding the offset. Check against a special constant.
8523     if (context->getStateCache().getNonInstancedVertexElementLimit() ==
8524             VertexAttribute::kIntegerOverflow ||
8525         context->getStateCache().getInstancedVertexElementLimit() ==
8526             VertexAttribute::kIntegerOverflow)
8527     {
8528         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
8529     }
8530     else
8531     {
8532         // [OpenGL ES 3.0.2] section 2.9.4 page 40:
8533         // We can return INVALID_OPERATION if our buffer does not have enough backing data.
8534         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
8535     }
8536 }
8537 
ValidateLoseContextCHROMIUM(const Context * context,angle::EntryPoint entryPoint,GraphicsResetStatus current,GraphicsResetStatus other)8538 bool ValidateLoseContextCHROMIUM(const Context *context,
8539                                  angle::EntryPoint entryPoint,
8540                                  GraphicsResetStatus current,
8541                                  GraphicsResetStatus other)
8542 {
8543     if (!context->getExtensions().loseContextCHROMIUM)
8544     {
8545         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8546         return false;
8547     }
8548 
8549     switch (current)
8550     {
8551         case GraphicsResetStatus::GuiltyContextReset:
8552         case GraphicsResetStatus::InnocentContextReset:
8553         case GraphicsResetStatus::UnknownContextReset:
8554             break;
8555 
8556         default:
8557             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus);
8558     }
8559 
8560     switch (other)
8561     {
8562         case GraphicsResetStatus::GuiltyContextReset:
8563         case GraphicsResetStatus::InnocentContextReset:
8564         case GraphicsResetStatus::UnknownContextReset:
8565             break;
8566 
8567         default:
8568             ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus);
8569     }
8570 
8571     return true;
8572 }
8573 
8574 // GL_ANGLE_texture_storage_external
ValidateTexImage2DExternalANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type)8575 bool ValidateTexImage2DExternalANGLE(const Context *context,
8576                                      angle::EntryPoint entryPoint,
8577                                      TextureTarget target,
8578                                      GLint level,
8579                                      GLint internalformat,
8580                                      GLsizei width,
8581                                      GLsizei height,
8582                                      GLint border,
8583                                      GLenum format,
8584                                      GLenum type)
8585 {
8586     if (!context->getExtensions().textureExternalUpdateANGLE)
8587     {
8588         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8589         return false;
8590     }
8591 
8592     if (!ValidTexture2DDestinationTarget(context, target) &&
8593         !ValidTextureExternalTarget(context, target))
8594     {
8595         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8596         return false;
8597     }
8598 
8599     if (context->getClientMajorVersion() <= 2)
8600     {
8601         if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
8602                                                false, false, 0, 0, width, height, border, format,
8603                                                type, -1, nullptr))
8604         {
8605             return false;
8606         }
8607     }
8608     else
8609     {
8610         if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat,
8611                                                false, false, 0, 0, 0, width, height, 1, border,
8612                                                format, type, -1, nullptr))
8613         {
8614             return false;
8615         }
8616     }
8617 
8618     return true;
8619 }
8620 
ValidateInvalidateTextureANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target)8621 bool ValidateInvalidateTextureANGLE(const Context *context,
8622                                     angle::EntryPoint entryPoint,
8623                                     TextureType target)
8624 {
8625     if (!context->getExtensions().textureExternalUpdateANGLE)
8626     {
8627         ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8628         return false;
8629     }
8630 
8631     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
8632     {
8633         ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8634         return false;
8635     }
8636 
8637     return true;
8638 }
8639 
ValidateProgramExecutableXFBBuffersPresent(const Context * context,const ProgramExecutable * programExecutable)8640 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
8641                                                 const ProgramExecutable *programExecutable)
8642 {
8643     size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
8644     const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
8645     for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
8646     {
8647         const OffsetBindingPointer<Buffer> &buffer =
8648             transformFeedback->getIndexedBuffer(programXfbIndex);
8649         if (!buffer.get())
8650         {
8651             return false;
8652         }
8653     }
8654 
8655     return true;
8656 }
8657 
ValidateLogicOpCommon(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,LogicalOperation opcodePacked)8658 bool ValidateLogicOpCommon(const PrivateState &state,
8659                            ErrorSet *errors,
8660                            angle::EntryPoint entryPoint,
8661                            LogicalOperation opcodePacked)
8662 {
8663     switch (opcodePacked)
8664     {
8665         case LogicalOperation::And:
8666         case LogicalOperation::AndInverted:
8667         case LogicalOperation::AndReverse:
8668         case LogicalOperation::Clear:
8669         case LogicalOperation::Copy:
8670         case LogicalOperation::CopyInverted:
8671         case LogicalOperation::Equiv:
8672         case LogicalOperation::Invert:
8673         case LogicalOperation::Nand:
8674         case LogicalOperation::Noop:
8675         case LogicalOperation::Nor:
8676         case LogicalOperation::Or:
8677         case LogicalOperation::OrInverted:
8678         case LogicalOperation::OrReverse:
8679         case LogicalOperation::Set:
8680         case LogicalOperation::Xor:
8681             return true;
8682         default:
8683             errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp);
8684             return false;
8685     }
8686 }
8687 }  // namespace gl
8688