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