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