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