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