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