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