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