1 //
2 // Copyright (c) 2013-2014 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/VertexArray.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/queryconversions.h"
24 #include "libANGLE/validationES2.h"
25 #include "libANGLE/validationES3.h"
26 
27 #include "common/mathutil.h"
28 #include "common/utilities.h"
29 
30 using namespace angle;
31 
32 namespace gl
33 {
34 namespace
35 {
36 
ValidateDrawAttribs(ValidationContext * context,GLint primcount,GLint maxVertex,GLint vertexCount)37 bool ValidateDrawAttribs(ValidationContext *context,
38                          GLint primcount,
39                          GLint maxVertex,
40                          GLint vertexCount)
41 {
42     const gl::State &state     = context->getGLState();
43     const gl::Program *program = state.getProgram();
44 
45     bool webglCompatibility = context->getExtensions().webglCompatibility;
46 
47     const VertexArray *vao     = state.getVertexArray();
48     const auto &vertexAttribs  = vao->getVertexAttributes();
49     const auto &vertexBindings = vao->getVertexBindings();
50     size_t maxEnabledAttrib    = vao->getMaxEnabledAttribute();
51     for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52     {
53         const VertexAttribute &attrib = vertexAttribs[attributeIndex];
54 
55         // No need to range check for disabled attribs.
56         if (!attrib.enabled)
57         {
58             continue;
59         }
60 
61         // If we have no buffer, then we either get an error, or there are no more checks to be
62         // done.
63         const VertexBinding &binding  = vertexBindings[attrib.bindingIndex];
64         gl::Buffer *buffer            = binding.getBuffer().get();
65         if (!buffer)
66         {
67             if (webglCompatibility || !state.areClientArraysEnabled())
68             {
69                 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
70                 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
71                 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
72                 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
73                 // error.
74                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
75                 return false;
76             }
77             else if (attrib.pointer == nullptr)
78             {
79                 // This is an application error that would normally result in a crash,
80                 // but we catch it and return an error
81                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
82                 return false;
83             }
84             continue;
85         }
86 
87         // This needs to come after the check for client arrays as even unused attributes cannot use
88         // client-side arrays
89         if (!program->isAttribLocationActive(attributeIndex))
90         {
91             continue;
92         }
93 
94         // If we're drawing zero vertices, we have enough data.
95         if (vertexCount <= 0 || primcount <= 0)
96         {
97             continue;
98         }
99 
100         GLint maxVertexElement = 0;
101         GLuint divisor         = binding.getDivisor();
102         if (divisor == 0)
103         {
104             maxVertexElement = maxVertex;
105         }
106         else
107         {
108             maxVertexElement = (primcount - 1) / divisor;
109         }
110 
111         // We do manual overflow checks here instead of using safe_math.h because it was
112         // a bottleneck. Thanks to some properties of GL we know inequalities that can
113         // help us make the overflow checks faster.
114 
115         // The max possible attribSize is 16 for a vector of 4 32 bit values.
116         constexpr uint64_t kMaxAttribSize = 16;
117         constexpr uint64_t kIntMax        = std::numeric_limits<int>::max();
118         constexpr uint64_t kUint64Max     = std::numeric_limits<uint64_t>::max();
119 
120         // We know attribStride is given as a GLsizei which is typedefed to int.
121         // We also know an upper bound for attribSize.
122         static_assert(std::is_same<int, GLsizei>::value, "");
123         uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
124         uint64_t attribSize   = ComputeVertexAttributeTypeSize(attrib);
125         ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
126 
127         // Computing the max offset using uint64_t without attrib.offset is overflow
128         // safe. Note: Last vertex element does not take the full stride!
129         static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
130         uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
131 
132         // An overflow can happen when adding the offset, check for it.
133         uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
134         if (attribDataSizeNoOffset > kUint64Max - attribOffset)
135         {
136             ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
137             return false;
138         }
139         uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
140 
141         // [OpenGL ES 3.0.2] section 2.9.4 page 40:
142         // We can return INVALID_OPERATION if our vertex attribute does not have
143         // enough backing data.
144         if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
145         {
146             ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
147             return false;
148         }
149     }
150 
151     return true;
152 }
153 
ValidReadPixelsTypeEnum(ValidationContext * context,GLenum type)154 bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
155 {
156     switch (type)
157     {
158         // Types referenced in Table 3.4 of the ES 2.0.25 spec
159         case GL_UNSIGNED_BYTE:
160         case GL_UNSIGNED_SHORT_4_4_4_4:
161         case GL_UNSIGNED_SHORT_5_5_5_1:
162         case GL_UNSIGNED_SHORT_5_6_5:
163             return context->getClientVersion() >= ES_2_0;
164 
165         // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
166         case GL_BYTE:
167         case GL_INT:
168         case GL_SHORT:
169         case GL_UNSIGNED_INT:
170         case GL_UNSIGNED_INT_10F_11F_11F_REV:
171         case GL_UNSIGNED_INT_24_8:
172         case GL_UNSIGNED_INT_2_10_10_10_REV:
173         case GL_UNSIGNED_INT_5_9_9_9_REV:
174         case GL_UNSIGNED_SHORT:
175         case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
176         case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
177             return context->getClientVersion() >= ES_3_0;
178 
179         case GL_FLOAT:
180             return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
181                    context->getExtensions().colorBufferHalfFloat;
182 
183         case GL_HALF_FLOAT:
184             return context->getClientVersion() >= ES_3_0 ||
185                    context->getExtensions().textureHalfFloat;
186 
187         case GL_HALF_FLOAT_OES:
188             return context->getExtensions().colorBufferHalfFloat;
189 
190         default:
191             return false;
192     }
193 }
194 
ValidReadPixelsFormatEnum(ValidationContext * context,GLenum format)195 bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
196 {
197     switch (format)
198     {
199         // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
200         case GL_RGBA:
201         case GL_RGB:
202         case GL_ALPHA:
203             return context->getClientVersion() >= ES_2_0;
204 
205         // Formats referenced in Table 3.2 of the ES 3.0.5 spec
206         case GL_RG:
207         case GL_RED:
208         case GL_RGBA_INTEGER:
209         case GL_RGB_INTEGER:
210         case GL_RG_INTEGER:
211         case GL_RED_INTEGER:
212             return context->getClientVersion() >= ES_3_0;
213 
214         case GL_SRGB_ALPHA_EXT:
215         case GL_SRGB_EXT:
216             return context->getExtensions().sRGB;
217 
218         case GL_BGRA_EXT:
219             return context->getExtensions().readFormatBGRA;
220 
221         default:
222             return false;
223     }
224 }
225 
ValidReadPixelsFormatType(ValidationContext * context,GLenum framebufferComponentType,GLenum format,GLenum type)226 bool ValidReadPixelsFormatType(ValidationContext *context,
227                                GLenum framebufferComponentType,
228                                GLenum format,
229                                GLenum type)
230 {
231     switch (framebufferComponentType)
232     {
233         case GL_UNSIGNED_NORMALIZED:
234             // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
235             // ReadPixels with BGRA even if the extension is not present
236             return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
237                    (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
238                     type == GL_UNSIGNED_BYTE);
239 
240         case GL_SIGNED_NORMALIZED:
241             return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
242 
243         case GL_INT:
244             return (format == GL_RGBA_INTEGER && type == GL_INT);
245 
246         case GL_UNSIGNED_INT:
247             return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
248 
249         case GL_FLOAT:
250             return (format == GL_RGBA && type == GL_FLOAT);
251 
252         default:
253             UNREACHABLE();
254             return false;
255     }
256 }
257 
258 template <typename ParamType>
ValidateTextureWrapModeValue(Context * context,ParamType * params,bool restrictedWrapModes)259 bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
260 {
261     switch (ConvertToGLenum(params[0]))
262     {
263         case GL_CLAMP_TO_EDGE:
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                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
272                 return false;
273             }
274             break;
275 
276         default:
277             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
278             return false;
279     }
280 
281     return true;
282 }
283 
284 template <typename ParamType>
ValidateTextureMinFilterValue(Context * context,ParamType * params,bool restrictedMinFilter)285 bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
286 {
287     switch (ConvertToGLenum(params[0]))
288     {
289         case GL_NEAREST:
290         case GL_LINEAR:
291             break;
292 
293         case GL_NEAREST_MIPMAP_NEAREST:
294         case GL_LINEAR_MIPMAP_NEAREST:
295         case GL_NEAREST_MIPMAP_LINEAR:
296         case GL_LINEAR_MIPMAP_LINEAR:
297             if (restrictedMinFilter)
298             {
299                 // OES_EGL_image_external specifies this error.
300                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
301                 return false;
302             }
303             break;
304 
305         default:
306             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
307             return false;
308     }
309 
310     return true;
311 }
312 
313 template <typename ParamType>
ValidateTextureMagFilterValue(Context * context,ParamType * params)314 bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
315 {
316     switch (ConvertToGLenum(params[0]))
317     {
318         case GL_NEAREST:
319         case GL_LINEAR:
320             break;
321 
322         default:
323             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
324             return false;
325     }
326 
327     return true;
328 }
329 
330 template <typename ParamType>
ValidateTextureCompareModeValue(Context * context,ParamType * params)331 bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
332 {
333     // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
334     switch (ConvertToGLenum(params[0]))
335     {
336         case GL_NONE:
337         case GL_COMPARE_REF_TO_TEXTURE:
338             break;
339 
340         default:
341             ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
342             return false;
343     }
344 
345     return true;
346 }
347 
348 template <typename ParamType>
ValidateTextureCompareFuncValue(Context * context,ParamType * params)349 bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
350 {
351     // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
352     switch (ConvertToGLenum(params[0]))
353     {
354         case GL_LEQUAL:
355         case GL_GEQUAL:
356         case GL_LESS:
357         case GL_GREATER:
358         case GL_EQUAL:
359         case GL_NOTEQUAL:
360         case GL_ALWAYS:
361         case GL_NEVER:
362             break;
363 
364         default:
365             ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
366             return false;
367     }
368 
369     return true;
370 }
371 
372 template <typename ParamType>
ValidateTextureSRGBDecodeValue(Context * context,ParamType * params)373 bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
374 {
375     if (!context->getExtensions().textureSRGBDecode)
376     {
377         ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
378         return false;
379     }
380 
381     switch (ConvertToGLenum(params[0]))
382     {
383         case GL_DECODE_EXT:
384         case GL_SKIP_DECODE_EXT:
385             break;
386 
387         default:
388             ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
389             return false;
390     }
391 
392     return true;
393 }
394 
ValidateFragmentShaderColorBufferTypeMatch(ValidationContext * context)395 bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
396 {
397     const Program *program         = context->getGLState().getProgram();
398     const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
399 
400     const auto &programOutputTypes = program->getOutputVariableTypes();
401     for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
402     {
403         GLenum outputType = programOutputTypes[drawBufferIdx];
404         GLenum inputType  = framebuffer->getDrawbufferWriteType(drawBufferIdx);
405         if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
406         {
407             context->handleError(InvalidOperation() << "Fragment shader output type does not "
408                                                        "match the bound framebuffer attachment "
409                                                        "type.");
410             return false;
411         }
412     }
413 
414     return true;
415 }
416 
ValidateVertexShaderAttributeTypeMatch(ValidationContext * context)417 bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
418 {
419     const auto &glState       = context->getGLState();
420     const Program *program = context->getGLState().getProgram();
421     const VertexArray *vao = context->getGLState().getVertexArray();
422     const auto &vertexAttribs = vao->getVertexAttributes();
423     const auto &currentValues = glState.getVertexAttribCurrentValues();
424 
425     for (const sh::Attribute &shaderAttribute : program->getAttributes())
426     {
427         // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
428         if (shaderAttribute.isBuiltIn())
429         {
430             continue;
431         }
432 
433         GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
434 
435         const auto &attrib = vertexAttribs[shaderAttribute.location];
436         GLenum vertexType  = attrib.enabled ? GetVertexAttributeBaseType(attrib)
437                                            : currentValues[shaderAttribute.location].Type;
438 
439         if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
440         {
441             context->handleError(InvalidOperation() << "Vertex shader input type does not "
442                                                        "match the type of the bound vertex "
443                                                        "attribute.");
444             return false;
445         }
446     }
447 
448     return true;
449 }
450 
451 }  // anonymous namespace
452 
ValidTextureTarget(const ValidationContext * context,GLenum target)453 bool ValidTextureTarget(const ValidationContext *context, GLenum target)
454 {
455     switch (target)
456     {
457         case GL_TEXTURE_2D:
458         case GL_TEXTURE_CUBE_MAP:
459             return true;
460 
461         case GL_TEXTURE_RECTANGLE_ANGLE:
462             return context->getExtensions().textureRectangle;
463 
464         case GL_TEXTURE_3D:
465         case GL_TEXTURE_2D_ARRAY:
466             return (context->getClientMajorVersion() >= 3);
467 
468         case GL_TEXTURE_2D_MULTISAMPLE:
469             return (context->getClientVersion() >= Version(3, 1));
470 
471         default:
472             return false;
473     }
474 }
475 
ValidTexture2DTarget(const ValidationContext * context,GLenum target)476 bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
477 {
478     switch (target)
479     {
480         case GL_TEXTURE_2D:
481         case GL_TEXTURE_CUBE_MAP:
482             return true;
483 
484         case GL_TEXTURE_RECTANGLE_ANGLE:
485             return context->getExtensions().textureRectangle;
486 
487         default:
488             return false;
489     }
490 }
491 
ValidTexture3DTarget(const ValidationContext * context,GLenum target)492 bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
493 {
494     switch (target)
495     {
496         case GL_TEXTURE_3D:
497         case GL_TEXTURE_2D_ARRAY:
498             return (context->getClientMajorVersion() >= 3);
499 
500         default:
501             return false;
502     }
503 }
504 
505 // Most texture GL calls are not compatible with external textures, so we have a separate validation
506 // function for use in the GL calls that do
ValidTextureExternalTarget(const ValidationContext * context,GLenum target)507 bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
508 {
509     return (target == GL_TEXTURE_EXTERNAL_OES) &&
510            (context->getExtensions().eglImageExternal ||
511             context->getExtensions().eglStreamConsumerExternal);
512 }
513 
514 // This function differs from ValidTextureTarget in that the target must be
515 // usable as the destination of a 2D operation-- so a cube face is valid, but
516 // GL_TEXTURE_CUBE_MAP is not.
517 // Note: duplicate of IsInternalTextureTarget
ValidTexture2DDestinationTarget(const ValidationContext * context,GLenum target)518 bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
519 {
520     switch (target)
521     {
522         case GL_TEXTURE_2D:
523         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
524         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
525         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
526         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
527         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
528         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
529             return true;
530         case GL_TEXTURE_RECTANGLE_ANGLE:
531             return context->getExtensions().textureRectangle;
532         default:
533             return false;
534     }
535 }
536 
ValidateDrawElementsInstancedBase(ValidationContext * context,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei primcount)537 bool ValidateDrawElementsInstancedBase(ValidationContext *context,
538                                        GLenum mode,
539                                        GLsizei count,
540                                        GLenum type,
541                                        const GLvoid *indices,
542                                        GLsizei primcount)
543 {
544     if (primcount < 0)
545     {
546         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
547         return false;
548     }
549 
550     if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
551     {
552         return false;
553     }
554 
555     // No-op zero primitive count
556     return (primcount > 0);
557 }
558 
ValidateDrawArraysInstancedBase(Context * context,GLenum mode,GLint first,GLsizei count,GLsizei primcount)559 bool ValidateDrawArraysInstancedBase(Context *context,
560                                      GLenum mode,
561                                      GLint first,
562                                      GLsizei count,
563                                      GLsizei primcount)
564 {
565     if (primcount < 0)
566     {
567         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
568         return false;
569     }
570 
571     if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
572     {
573         return false;
574     }
575 
576     // No-op if zero primitive count
577     return (primcount > 0);
578 }
579 
ValidateDrawInstancedANGLE(ValidationContext * context)580 bool ValidateDrawInstancedANGLE(ValidationContext *context)
581 {
582     // Verify there is at least one active attribute with a divisor of zero
583     const State &state = context->getGLState();
584 
585     Program *program = state.getProgram();
586 
587     const auto &attribs  = state.getVertexArray()->getVertexAttributes();
588     const auto &bindings = state.getVertexArray()->getVertexBindings();
589     for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
590     {
591         const VertexAttribute &attrib = attribs[attributeIndex];
592         const VertexBinding &binding  = bindings[attrib.bindingIndex];
593         if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
594         {
595             return true;
596         }
597     }
598 
599     ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
600     return false;
601 }
602 
ValidTexture3DDestinationTarget(const ValidationContext * context,GLenum target)603 bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
604 {
605     switch (target)
606     {
607         case GL_TEXTURE_3D:
608         case GL_TEXTURE_2D_ARRAY:
609             return true;
610         default:
611             return false;
612     }
613 }
614 
ValidTexLevelDestinationTarget(const ValidationContext * context,GLenum target)615 bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
616 {
617     switch (target)
618     {
619         case GL_TEXTURE_2D:
620         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
621         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
622         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
623         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
624         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
625         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
626         case GL_TEXTURE_3D:
627         case GL_TEXTURE_2D_ARRAY:
628         case GL_TEXTURE_2D_MULTISAMPLE:
629             return true;
630         case GL_TEXTURE_RECTANGLE_ANGLE:
631             return context->getExtensions().textureRectangle;
632         default:
633             return false;
634     }
635 }
636 
ValidFramebufferTarget(const ValidationContext * context,GLenum target)637 bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
638 {
639     static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
640                       GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
641                   "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
642 
643     switch (target)
644     {
645         case GL_FRAMEBUFFER:
646             return true;
647 
648         case GL_READ_FRAMEBUFFER:
649         case GL_DRAW_FRAMEBUFFER:
650             return (context->getExtensions().framebufferBlit ||
651                     context->getClientMajorVersion() >= 3);
652 
653         default:
654             return false;
655     }
656 }
657 
ValidBufferType(const ValidationContext * context,BufferBinding target)658 bool ValidBufferType(const ValidationContext *context, BufferBinding target)
659 {
660     switch (target)
661     {
662         case BufferBinding::ElementArray:
663         case BufferBinding::Array:
664             return true;
665 
666         case BufferBinding::PixelPack:
667         case BufferBinding::PixelUnpack:
668             return (context->getExtensions().pixelBufferObject ||
669                     context->getClientMajorVersion() >= 3);
670 
671         case BufferBinding::CopyRead:
672         case BufferBinding::CopyWrite:
673         case BufferBinding::TransformFeedback:
674         case BufferBinding::Uniform:
675             return (context->getClientMajorVersion() >= 3);
676 
677         case BufferBinding::AtomicCounter:
678         case BufferBinding::ShaderStorage:
679         case BufferBinding::DrawIndirect:
680         case BufferBinding::DispatchIndirect:
681             return context->getClientVersion() >= Version(3, 1);
682 
683         default:
684             return false;
685     }
686 }
687 
ValidMipLevel(const ValidationContext * context,GLenum target,GLint level)688 bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
689 {
690     const auto &caps    = context->getCaps();
691     size_t maxDimension = 0;
692     switch (target)
693     {
694         case GL_TEXTURE_2D:
695             maxDimension = caps.max2DTextureSize;
696             break;
697         case GL_TEXTURE_CUBE_MAP:
698         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
699         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
700         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
701         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
702         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
703         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
704             maxDimension = caps.maxCubeMapTextureSize;
705             break;
706         case GL_TEXTURE_RECTANGLE_ANGLE:
707             return level == 0;
708         case GL_TEXTURE_3D:
709             maxDimension = caps.max3DTextureSize;
710             break;
711         case GL_TEXTURE_2D_ARRAY:
712             maxDimension = caps.max2DTextureSize;
713             break;
714         case GL_TEXTURE_2D_MULTISAMPLE:
715             maxDimension = caps.max2DTextureSize;
716             break;
717         default:
718             UNREACHABLE();
719     }
720 
721     return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
722 }
723 
ValidImageSizeParameters(ValidationContext * context,GLenum target,GLint level,GLsizei width,GLsizei height,GLsizei depth,bool isSubImage)724 bool ValidImageSizeParameters(ValidationContext *context,
725                               GLenum target,
726                               GLint level,
727                               GLsizei width,
728                               GLsizei height,
729                               GLsizei depth,
730                               bool isSubImage)
731 {
732     if (width < 0 || height < 0 || depth < 0)
733     {
734         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
735         return false;
736     }
737     // TexSubImage parameters can be NPOT without textureNPOT extension,
738     // as long as the destination texture is POT.
739     bool hasNPOTSupport =
740         context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
741     if (!isSubImage && !hasNPOTSupport &&
742         (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
743     {
744         ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
745         return false;
746     }
747 
748     if (!ValidMipLevel(context, target, level))
749     {
750         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
751         return false;
752     }
753 
754     return true;
755 }
756 
CompressedTextureFormatRequiresExactSize(GLenum internalFormat)757 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
758 {
759     // List of compressed format that require that the texture size is smaller than or a multiple of
760     // the compressed block size.
761     switch (internalFormat)
762     {
763         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
764         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
765         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
766         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
767         case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
768         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
769         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
770         case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
771         case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
772         case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
773         case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
774         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
775         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
776         case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
777         case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
778             return true;
779 
780         default:
781             return false;
782     }
783 }
784 
ValidCompressedDimension(GLsizei size,GLuint blockSize,bool smallerThanBlockSizeAllowed)785 bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
786 {
787     return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
788            (size % blockSize == 0);
789 }
790 
ValidCompressedImageSize(const ValidationContext * context,GLenum internalFormat,GLint level,GLsizei width,GLsizei height)791 bool ValidCompressedImageSize(const ValidationContext *context,
792                               GLenum internalFormat,
793                               GLint level,
794                               GLsizei width,
795                               GLsizei height)
796 {
797     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
798     if (!formatInfo.compressed)
799     {
800         return false;
801     }
802 
803     if (width < 0 || height < 0)
804     {
805         return false;
806     }
807 
808     if (CompressedTextureFormatRequiresExactSize(internalFormat))
809     {
810         // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
811         // block size for level 0 but WebGL disallows this.
812         bool smallerThanBlockSizeAllowed =
813             level > 0 || !context->getExtensions().webglCompatibility;
814 
815         if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
816                                       smallerThanBlockSizeAllowed) ||
817             !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
818                                       smallerThanBlockSizeAllowed))
819         {
820             return false;
821         }
822     }
823 
824     return true;
825 }
826 
ValidCompressedSubImageSize(const ValidationContext * context,GLenum internalFormat,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,size_t textureWidth,size_t textureHeight)827 bool ValidCompressedSubImageSize(const ValidationContext *context,
828                                  GLenum internalFormat,
829                                  GLint xoffset,
830                                  GLint yoffset,
831                                  GLsizei width,
832                                  GLsizei height,
833                                  size_t textureWidth,
834                                  size_t textureHeight)
835 {
836     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
837     if (!formatInfo.compressed)
838     {
839         return false;
840     }
841 
842     if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
843     {
844         return false;
845     }
846 
847     if (CompressedTextureFormatRequiresExactSize(internalFormat))
848     {
849         if (xoffset % formatInfo.compressedBlockWidth != 0 ||
850             yoffset % formatInfo.compressedBlockHeight != 0)
851         {
852             return false;
853         }
854 
855         // Allowed to either have data that is a multiple of block size or is smaller than the block
856         // size but fills the entire mip
857         bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
858                               static_cast<size_t>(width) == textureWidth &&
859                               static_cast<size_t>(height) == textureHeight;
860         bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
861                                        (height % formatInfo.compressedBlockHeight) == 0;
862         if (!sizeMultipleOfBlockSize && !fillsEntireMip)
863         {
864             return false;
865         }
866     }
867 
868     return true;
869 }
870 
ValidImageDataSize(ValidationContext * context,GLenum textureTarget,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels,GLsizei imageSize)871 bool ValidImageDataSize(ValidationContext *context,
872                         GLenum textureTarget,
873                         GLsizei width,
874                         GLsizei height,
875                         GLsizei depth,
876                         GLenum format,
877                         GLenum type,
878                         const void *pixels,
879                         GLsizei imageSize)
880 {
881     gl::Buffer *pixelUnpackBuffer =
882         context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
883     if (pixelUnpackBuffer == nullptr && imageSize < 0)
884     {
885         // Checks are not required
886         return true;
887     }
888 
889     // ...the data would be unpacked from the buffer object such that the memory reads required
890     // would exceed the data store size.
891     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
892     ASSERT(formatInfo.internalFormat != GL_NONE);
893     const gl::Extents size(width, height, depth);
894     const auto &unpack = context->getGLState().getUnpackState();
895 
896     bool targetIs3D   = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
897     auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
898     if (endByteOrErr.isError())
899     {
900         context->handleError(endByteOrErr.getError());
901         return false;
902     }
903 
904     GLuint endByte = endByteOrErr.getResult();
905 
906     if (pixelUnpackBuffer)
907     {
908         CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
909         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
910         checkedEndByte += checkedOffset;
911 
912         if (!checkedEndByte.IsValid() ||
913             (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
914         {
915             // Overflow past the end of the buffer
916             context->handleError(InvalidOperation());
917             return false;
918         }
919     }
920     else
921     {
922         ASSERT(imageSize >= 0);
923         if (pixels == nullptr && imageSize != 0)
924         {
925             context->handleError(InvalidOperation()
926                                  << "imageSize must be 0 if no texture data is provided.");
927             return false;
928         }
929 
930         if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
931         {
932             context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
933             return false;
934         }
935     }
936 
937     return true;
938 }
939 
ValidQueryType(const Context * context,GLenum queryType)940 bool ValidQueryType(const Context *context, GLenum queryType)
941 {
942     static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
943                   "GL extension enums not equal.");
944     static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
945                   "GL extension enums not equal.");
946 
947     switch (queryType)
948     {
949         case GL_ANY_SAMPLES_PASSED:
950         case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
951             return context->getClientMajorVersion() >= 3 ||
952                    context->getExtensions().occlusionQueryBoolean;
953         case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
954             return (context->getClientMajorVersion() >= 3);
955         case GL_TIME_ELAPSED_EXT:
956             return context->getExtensions().disjointTimerQuery;
957         case GL_COMMANDS_COMPLETED_CHROMIUM:
958             return context->getExtensions().syncQuery;
959         default:
960             return false;
961     }
962 }
963 
ValidateWebGLVertexAttribPointer(ValidationContext * context,GLenum type,GLboolean normalized,GLsizei stride,const void * ptr,bool pureInteger)964 bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
965                                       GLenum type,
966                                       GLboolean normalized,
967                                       GLsizei stride,
968                                       const void *ptr,
969                                       bool pureInteger)
970 {
971     ASSERT(context->getExtensions().webglCompatibility);
972     // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
973     // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
974     // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
975     // parameter exceeds 255.
976     constexpr GLsizei kMaxWebGLStride = 255;
977     if (stride > kMaxWebGLStride)
978     {
979         context->handleError(InvalidValue()
980                              << "Stride is over the maximum stride allowed by WebGL.");
981         return false;
982     }
983 
984     // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
985     // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
986     // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
987     // or an INVALID_OPERATION error is generated.
988     VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
989     size_t typeSize               = GetVertexFormatTypeSize(internalType);
990 
991     ASSERT(isPow2(typeSize) && typeSize > 0);
992     size_t sizeMask = (typeSize - 1);
993     if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
994     {
995         ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
996         return false;
997     }
998 
999     if ((stride & sizeMask) != 0)
1000     {
1001         ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
1002         return false;
1003     }
1004 
1005     return true;
1006 }
1007 
GetValidProgram(ValidationContext * context,GLuint id)1008 Program *GetValidProgram(ValidationContext *context, GLuint id)
1009 {
1010     // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1011     // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1012     // or program object and INVALID_OPERATION if the provided name identifies an object
1013     // that is not the expected type."
1014 
1015     Program *validProgram = context->getProgram(id);
1016 
1017     if (!validProgram)
1018     {
1019         if (context->getShader(id))
1020         {
1021             ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
1022         }
1023         else
1024         {
1025             ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
1026         }
1027     }
1028 
1029     return validProgram;
1030 }
1031 
GetValidShader(ValidationContext * context,GLuint id)1032 Shader *GetValidShader(ValidationContext *context, GLuint id)
1033 {
1034     // See ValidProgram for spec details.
1035 
1036     Shader *validShader = context->getShader(id);
1037 
1038     if (!validShader)
1039     {
1040         if (context->getProgram(id))
1041         {
1042             ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
1043         }
1044         else
1045         {
1046             ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
1047         }
1048     }
1049 
1050     return validShader;
1051 }
1052 
ValidateAttachmentTarget(gl::Context * context,GLenum attachment)1053 bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
1054 {
1055     if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1056     {
1057         if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1058         {
1059             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1060             return false;
1061         }
1062 
1063         // Color attachment 0 is validated below because it is always valid
1064         const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1065         if (colorAttachment >= context->getCaps().maxColorAttachments)
1066         {
1067             ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
1068             return false;
1069         }
1070     }
1071     else
1072     {
1073         switch (attachment)
1074         {
1075             case GL_COLOR_ATTACHMENT0:
1076             case GL_DEPTH_ATTACHMENT:
1077             case GL_STENCIL_ATTACHMENT:
1078                 break;
1079 
1080             case GL_DEPTH_STENCIL_ATTACHMENT:
1081                 if (!context->getExtensions().webglCompatibility &&
1082                     context->getClientMajorVersion() < 3)
1083                 {
1084                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1085                     return false;
1086                 }
1087                 break;
1088 
1089             default:
1090                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1091                 return false;
1092         }
1093     }
1094 
1095     return true;
1096 }
1097 
ValidateRenderbufferStorageParametersBase(ValidationContext * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1098 bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
1099                                                GLenum target,
1100                                                GLsizei samples,
1101                                                GLenum internalformat,
1102                                                GLsizei width,
1103                                                GLsizei height)
1104 {
1105     switch (target)
1106     {
1107         case GL_RENDERBUFFER:
1108             break;
1109         default:
1110             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
1111             return false;
1112     }
1113 
1114     if (width < 0 || height < 0 || samples < 0)
1115     {
1116         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
1117         return false;
1118     }
1119 
1120     // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1121     GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1122 
1123     const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
1124     if (!formatCaps.renderable)
1125     {
1126         context->handleError(InvalidEnum());
1127         return false;
1128     }
1129 
1130     // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1131     // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
1132     // only sized internal formats.
1133     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1134     if (formatInfo.internalFormat == GL_NONE)
1135     {
1136         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
1137         return false;
1138     }
1139 
1140     if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
1141     {
1142         context->handleError(InvalidValue());
1143         return false;
1144     }
1145 
1146     GLuint handle = context->getGLState().getRenderbufferId();
1147     if (handle == 0)
1148     {
1149         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
1150         return false;
1151     }
1152 
1153     return true;
1154 }
1155 
ValidateFramebufferRenderbufferParameters(gl::Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)1156 bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1157                                                GLenum target,
1158                                                GLenum attachment,
1159                                                GLenum renderbuffertarget,
1160                                                GLuint renderbuffer)
1161 {
1162     if (!ValidFramebufferTarget(context, target))
1163     {
1164         context->handleError(InvalidEnum());
1165         return false;
1166     }
1167 
1168     gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1169 
1170     ASSERT(framebuffer);
1171     if (framebuffer->id() == 0)
1172     {
1173         ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
1174         return false;
1175     }
1176 
1177     if (!ValidateAttachmentTarget(context, attachment))
1178     {
1179         return false;
1180     }
1181 
1182     // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1183     // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1184     // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1185     // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1186     if (renderbuffer != 0)
1187     {
1188         if (!context->getRenderbuffer(renderbuffer))
1189         {
1190             ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
1191             return false;
1192         }
1193     }
1194 
1195     return true;
1196 }
1197 
ValidateBlitFramebufferParameters(ValidationContext * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1198 bool ValidateBlitFramebufferParameters(ValidationContext *context,
1199                                        GLint srcX0,
1200                                        GLint srcY0,
1201                                        GLint srcX1,
1202                                        GLint srcY1,
1203                                        GLint dstX0,
1204                                        GLint dstY0,
1205                                        GLint dstX1,
1206                                        GLint dstY1,
1207                                        GLbitfield mask,
1208                                        GLenum filter)
1209 {
1210     switch (filter)
1211     {
1212         case GL_NEAREST:
1213             break;
1214         case GL_LINEAR:
1215             break;
1216         default:
1217             context->handleError(InvalidEnum());
1218             return false;
1219     }
1220 
1221     if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1222     {
1223         context->handleError(InvalidValue());
1224         return false;
1225     }
1226 
1227     if (mask == 0)
1228     {
1229         // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1230         // buffers are copied.
1231         return false;
1232     }
1233 
1234     // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1235     // color buffer, leaving only nearest being unfiltered from above
1236     if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1237     {
1238         context->handleError(InvalidOperation());
1239         return false;
1240     }
1241 
1242     const auto &glState              = context->getGLState();
1243     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1244     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1245 
1246     if (!readFramebuffer || !drawFramebuffer)
1247     {
1248         context->handleError(InvalidFramebufferOperation());
1249         return false;
1250     }
1251 
1252     if (readFramebuffer->id() == drawFramebuffer->id())
1253     {
1254         context->handleError(InvalidOperation());
1255         return false;
1256     }
1257 
1258     if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
1259     {
1260         context->handleError(InvalidFramebufferOperation());
1261         return false;
1262     }
1263 
1264     if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
1265     {
1266         context->handleError(InvalidFramebufferOperation());
1267         return false;
1268     }
1269 
1270     if (drawFramebuffer->getSamples(context) != 0)
1271     {
1272         context->handleError(InvalidOperation());
1273         return false;
1274     }
1275 
1276     bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1277 
1278     if (mask & GL_COLOR_BUFFER_BIT)
1279     {
1280         const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1281         const Extensions &extensions                     = context->getExtensions();
1282 
1283         if (readColorBuffer)
1284         {
1285             const Format &readFormat = readColorBuffer->getFormat();
1286 
1287             for (size_t drawbufferIdx = 0;
1288                  drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
1289             {
1290                 const FramebufferAttachment *attachment =
1291                     drawFramebuffer->getDrawBuffer(drawbufferIdx);
1292                 if (attachment)
1293                 {
1294                     const Format &drawFormat = attachment->getFormat();
1295 
1296                     // The GL ES 3.0.2 spec (pg 193) states that:
1297                     // 1) If the read buffer is fixed point format, the draw buffer must be as well
1298                     // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1299                     // as well
1300                     // 3) If the read buffer is a signed integer format, the draw buffer must be as
1301                     // well
1302                     // Changes with EXT_color_buffer_float:
1303                     // Case 1) is changed to fixed point OR floating point
1304                     GLenum readComponentType = readFormat.info->componentType;
1305                     GLenum drawComponentType = drawFormat.info->componentType;
1306                     bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1307                                            readComponentType == GL_SIGNED_NORMALIZED);
1308                     bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1309                                            drawComponentType == GL_SIGNED_NORMALIZED);
1310 
1311                     if (extensions.colorBufferFloat)
1312                     {
1313                         bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1314                         bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1315 
1316                         if (readFixedOrFloat != drawFixedOrFloat)
1317                         {
1318                             context->handleError(InvalidOperation()
1319                                                  << "If the read buffer contains fixed-point or "
1320                                                     "floating-point values, the draw buffer must "
1321                                                     "as well.");
1322                             return false;
1323                         }
1324                     }
1325                     else if (readFixedPoint != drawFixedPoint)
1326                     {
1327                         context->handleError(InvalidOperation()
1328                                              << "If the read buffer contains fixed-point values, "
1329                                                 "the draw buffer must as well.");
1330                         return false;
1331                     }
1332 
1333                     if (readComponentType == GL_UNSIGNED_INT &&
1334                         drawComponentType != GL_UNSIGNED_INT)
1335                     {
1336                         context->handleError(InvalidOperation());
1337                         return false;
1338                     }
1339 
1340                     if (readComponentType == GL_INT && drawComponentType != GL_INT)
1341                     {
1342                         context->handleError(InvalidOperation());
1343                         return false;
1344                     }
1345 
1346                     if (readColorBuffer->getSamples() > 0 &&
1347                         (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
1348                     {
1349                         context->handleError(InvalidOperation());
1350                         return false;
1351                     }
1352 
1353                     if (context->getExtensions().webglCompatibility &&
1354                         *readColorBuffer == *attachment)
1355                     {
1356                         context->handleError(
1357                             InvalidOperation()
1358                             << "Read and write color attachments cannot be the same image.");
1359                         return false;
1360                     }
1361                 }
1362             }
1363 
1364             if ((readFormat.info->componentType == GL_INT ||
1365                  readFormat.info->componentType == GL_UNSIGNED_INT) &&
1366                 filter == GL_LINEAR)
1367             {
1368                 context->handleError(InvalidOperation());
1369                 return false;
1370             }
1371         }
1372         // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1373         // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1374         // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1375         // situation is an application error that would lead to a crash in ANGLE.
1376         else if (drawFramebuffer->hasEnabledDrawBuffer())
1377         {
1378             context->handleError(
1379                 InvalidOperation()
1380                 << "Attempt to read from a missing color attachment of a complete framebuffer.");
1381             return false;
1382         }
1383     }
1384 
1385     GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1386     GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1387     for (size_t i = 0; i < 2; i++)
1388     {
1389         if (mask & masks[i])
1390         {
1391             const gl::FramebufferAttachment *readBuffer =
1392                 readFramebuffer->getAttachment(attachments[i]);
1393             const gl::FramebufferAttachment *drawBuffer =
1394                 drawFramebuffer->getAttachment(attachments[i]);
1395 
1396             if (readBuffer && drawBuffer)
1397             {
1398                 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
1399                 {
1400                     context->handleError(InvalidOperation());
1401                     return false;
1402                 }
1403 
1404                 if (readBuffer->getSamples() > 0 && !sameBounds)
1405                 {
1406                     context->handleError(InvalidOperation());
1407                     return false;
1408                 }
1409 
1410                 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1411                 {
1412                     context->handleError(
1413                         InvalidOperation()
1414                         << "Read and write depth stencil attachments cannot be the same image.");
1415                     return false;
1416                 }
1417             }
1418             // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1419             else if (drawBuffer)
1420             {
1421                 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1422                                                            "depth/stencil attachment of a "
1423                                                            "complete framebuffer.");
1424                 return false;
1425             }
1426         }
1427     }
1428 
1429     // ANGLE_multiview, Revision 1:
1430     // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1431     // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1432     if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1433     {
1434         context->handleError(InvalidFramebufferOperation()
1435                              << "Attempt to read from a multi-view framebuffer.");
1436         return false;
1437     }
1438     if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1439     {
1440         context->handleError(InvalidFramebufferOperation()
1441                              << "Attempt to write to a multi-view framebuffer.");
1442         return false;
1443     }
1444 
1445     return true;
1446 }
1447 
ValidateReadPixelsRobustANGLE(Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,void * pixels)1448 bool ValidateReadPixelsRobustANGLE(Context *context,
1449                                    GLint x,
1450                                    GLint y,
1451                                    GLsizei width,
1452                                    GLsizei height,
1453                                    GLenum format,
1454                                    GLenum type,
1455                                    GLsizei bufSize,
1456                                    GLsizei *length,
1457                                    GLsizei *columns,
1458                                    GLsizei *rows,
1459                                    void *pixels)
1460 {
1461     if (!ValidateRobustEntryPoint(context, bufSize))
1462     {
1463         return false;
1464     }
1465 
1466     if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1467                                 columns, rows, pixels))
1468     {
1469         return false;
1470     }
1471 
1472     if (!ValidateRobustBufferSize(context, bufSize, *length))
1473     {
1474         return false;
1475     }
1476 
1477     return true;
1478 }
1479 
ValidateReadnPixelsEXT(Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,void * pixels)1480 bool ValidateReadnPixelsEXT(Context *context,
1481                             GLint x,
1482                             GLint y,
1483                             GLsizei width,
1484                             GLsizei height,
1485                             GLenum format,
1486                             GLenum type,
1487                             GLsizei bufSize,
1488                             void *pixels)
1489 {
1490     if (bufSize < 0)
1491     {
1492         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
1493         return false;
1494     }
1495 
1496     return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1497                                   nullptr, nullptr, pixels);
1498 }
1499 
ValidateReadnPixelsRobustANGLE(Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,void * data)1500 bool ValidateReadnPixelsRobustANGLE(Context *context,
1501                                     GLint x,
1502                                     GLint y,
1503                                     GLsizei width,
1504                                     GLsizei height,
1505                                     GLenum format,
1506                                     GLenum type,
1507                                     GLsizei bufSize,
1508                                     GLsizei *length,
1509                                     GLsizei *columns,
1510                                     GLsizei *rows,
1511                                     void *data)
1512 {
1513     if (!ValidateRobustEntryPoint(context, bufSize))
1514     {
1515         return false;
1516     }
1517 
1518     if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1519                                 columns, rows, data))
1520     {
1521         return false;
1522     }
1523 
1524     if (!ValidateRobustBufferSize(context, bufSize, *length))
1525     {
1526         return false;
1527     }
1528 
1529     return true;
1530 }
1531 
ValidateGenQueriesEXT(gl::Context * context,GLsizei n,GLuint * ids)1532 bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
1533 {
1534     if (!context->getExtensions().occlusionQueryBoolean &&
1535         !context->getExtensions().disjointTimerQuery)
1536     {
1537         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1538         return false;
1539     }
1540 
1541     return ValidateGenOrDelete(context, n);
1542 }
1543 
ValidateDeleteQueriesEXT(gl::Context * context,GLsizei n,const GLuint * ids)1544 bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
1545 {
1546     if (!context->getExtensions().occlusionQueryBoolean &&
1547         !context->getExtensions().disjointTimerQuery)
1548     {
1549         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1550         return false;
1551     }
1552 
1553     return ValidateGenOrDelete(context, n);
1554 }
1555 
ValidateIsQueryEXT(gl::Context * context,GLuint id)1556 bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1557 {
1558     if (!context->getExtensions().occlusionQueryBoolean &&
1559         !context->getExtensions().disjointTimerQuery)
1560     {
1561         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1562         return false;
1563     }
1564 
1565     return true;
1566 }
1567 
ValidateBeginQueryBase(gl::Context * context,GLenum target,GLuint id)1568 bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
1569 {
1570     if (!ValidQueryType(context, target))
1571     {
1572         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
1573         return false;
1574     }
1575 
1576     if (id == 0)
1577     {
1578         context->handleError(InvalidOperation() << "Query id is 0");
1579         return false;
1580     }
1581 
1582     // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1583     // of zero, if the active query object name for <target> is non-zero (for the
1584     // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1585     // the active query for either target is non-zero), if <id> is the name of an
1586     // existing query object whose type does not match <target>, or if <id> is the
1587     // active query object name for any query type, the error INVALID_OPERATION is
1588     // generated.
1589 
1590     // Ensure no other queries are active
1591     // NOTE: If other queries than occlusion are supported, we will need to check
1592     // separately that:
1593     //    a) The query ID passed is not the current active query for any target/type
1594     //    b) There are no active queries for the requested target (and in the case
1595     //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1596     //       no query may be active for either if glBeginQuery targets either.
1597 
1598     if (context->getGLState().isQueryActive(target))
1599     {
1600         context->handleError(InvalidOperation() << "Other query is active");
1601         return false;
1602     }
1603 
1604     Query *queryObject = context->getQuery(id, true, target);
1605 
1606     // check that name was obtained with glGenQueries
1607     if (!queryObject)
1608     {
1609         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
1610         return false;
1611     }
1612 
1613     // check for type mismatch
1614     if (queryObject->getType() != target)
1615     {
1616         context->handleError(InvalidOperation() << "Query type does not match target");
1617         return false;
1618     }
1619 
1620     return true;
1621 }
1622 
ValidateBeginQueryEXT(gl::Context * context,GLenum target,GLuint id)1623 bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1624 {
1625     if (!context->getExtensions().occlusionQueryBoolean &&
1626         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1627     {
1628         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1629         return false;
1630     }
1631 
1632     return ValidateBeginQueryBase(context, target, id);
1633 }
1634 
ValidateEndQueryBase(gl::Context * context,GLenum target)1635 bool ValidateEndQueryBase(gl::Context *context, GLenum target)
1636 {
1637     if (!ValidQueryType(context, target))
1638     {
1639         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
1640         return false;
1641     }
1642 
1643     const Query *queryObject = context->getGLState().getActiveQuery(target);
1644 
1645     if (queryObject == nullptr)
1646     {
1647         context->handleError(InvalidOperation() << "Query target not active");
1648         return false;
1649     }
1650 
1651     return true;
1652 }
1653 
ValidateEndQueryEXT(gl::Context * context,GLenum target)1654 bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1655 {
1656     if (!context->getExtensions().occlusionQueryBoolean &&
1657         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1658     {
1659         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1660         return false;
1661     }
1662 
1663     return ValidateEndQueryBase(context, target);
1664 }
1665 
ValidateQueryCounterEXT(Context * context,GLuint id,GLenum target)1666 bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1667 {
1668     if (!context->getExtensions().disjointTimerQuery)
1669     {
1670         context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
1671         return false;
1672     }
1673 
1674     if (target != GL_TIMESTAMP_EXT)
1675     {
1676         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
1677         return false;
1678     }
1679 
1680     Query *queryObject = context->getQuery(id, true, target);
1681     if (queryObject == nullptr)
1682     {
1683         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
1684         return false;
1685     }
1686 
1687     if (context->getGLState().isQueryActive(queryObject))
1688     {
1689         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
1690         return false;
1691     }
1692 
1693     return true;
1694 }
1695 
ValidateGetQueryivBase(Context * context,GLenum target,GLenum pname,GLsizei * numParams)1696 bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
1697 {
1698     if (numParams)
1699     {
1700         *numParams = 0;
1701     }
1702 
1703     if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1704     {
1705         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
1706         return false;
1707     }
1708 
1709     switch (pname)
1710     {
1711         case GL_CURRENT_QUERY_EXT:
1712             if (target == GL_TIMESTAMP_EXT)
1713             {
1714                 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
1715                 return false;
1716             }
1717             break;
1718         case GL_QUERY_COUNTER_BITS_EXT:
1719             if (!context->getExtensions().disjointTimerQuery ||
1720                 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1721             {
1722                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
1723                 return false;
1724             }
1725             break;
1726         default:
1727             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
1728             return false;
1729     }
1730 
1731     if (numParams)
1732     {
1733         // All queries return only one value
1734         *numParams = 1;
1735     }
1736 
1737     return true;
1738 }
1739 
ValidateGetQueryivEXT(Context * context,GLenum target,GLenum pname,GLint * params)1740 bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1741 {
1742     if (!context->getExtensions().occlusionQueryBoolean &&
1743         !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1744     {
1745         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1746         return false;
1747     }
1748 
1749     return ValidateGetQueryivBase(context, target, pname, nullptr);
1750 }
1751 
ValidateGetQueryivRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)1752 bool ValidateGetQueryivRobustANGLE(Context *context,
1753                                    GLenum target,
1754                                    GLenum pname,
1755                                    GLsizei bufSize,
1756                                    GLsizei *length,
1757                                    GLint *params)
1758 {
1759     if (!ValidateRobustEntryPoint(context, bufSize))
1760     {
1761         return false;
1762     }
1763 
1764     if (!ValidateGetQueryivBase(context, target, pname, length))
1765     {
1766         return false;
1767     }
1768 
1769     if (!ValidateRobustBufferSize(context, bufSize, *length))
1770     {
1771         return false;
1772     }
1773 
1774     return true;
1775 }
1776 
ValidateGetQueryObjectValueBase(Context * context,GLuint id,GLenum pname,GLsizei * numParams)1777 bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1778 {
1779     if (numParams)
1780     {
1781         *numParams = 0;
1782     }
1783 
1784     Query *queryObject = context->getQuery(id, false, GL_NONE);
1785 
1786     if (!queryObject)
1787     {
1788         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
1789         return false;
1790     }
1791 
1792     if (context->getGLState().isQueryActive(queryObject))
1793     {
1794         ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
1795         return false;
1796     }
1797 
1798     switch (pname)
1799     {
1800         case GL_QUERY_RESULT_EXT:
1801         case GL_QUERY_RESULT_AVAILABLE_EXT:
1802             break;
1803 
1804         default:
1805             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
1806             return false;
1807     }
1808 
1809     if (numParams)
1810     {
1811         *numParams = 1;
1812     }
1813 
1814     return true;
1815 }
1816 
ValidateGetQueryObjectivEXT(Context * context,GLuint id,GLenum pname,GLint * params)1817 bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1818 {
1819     if (!context->getExtensions().disjointTimerQuery)
1820     {
1821         context->handleError(InvalidOperation() << "Timer query extension not enabled");
1822         return false;
1823     }
1824     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1825 }
1826 
ValidateGetQueryObjectivRobustANGLE(Context * context,GLuint id,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)1827 bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1828                                          GLuint id,
1829                                          GLenum pname,
1830                                          GLsizei bufSize,
1831                                          GLsizei *length,
1832                                          GLint *params)
1833 {
1834     if (!context->getExtensions().disjointTimerQuery)
1835     {
1836         context->handleError(InvalidOperation() << "Timer query extension not enabled");
1837         return false;
1838     }
1839 
1840     if (!ValidateRobustEntryPoint(context, bufSize))
1841     {
1842         return false;
1843     }
1844 
1845     if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1846     {
1847         return false;
1848     }
1849 
1850     if (!ValidateRobustBufferSize(context, bufSize, *length))
1851     {
1852         return false;
1853     }
1854 
1855     return true;
1856 }
1857 
ValidateGetQueryObjectuivEXT(Context * context,GLuint id,GLenum pname,GLuint * params)1858 bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1859 {
1860     if (!context->getExtensions().disjointTimerQuery &&
1861         !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1862     {
1863         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1864         return false;
1865     }
1866     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1867 }
1868 
ValidateGetQueryObjectuivRobustANGLE(Context * context,GLuint id,GLenum pname,GLsizei bufSize,GLsizei * length,GLuint * params)1869 bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1870                                           GLuint id,
1871                                           GLenum pname,
1872                                           GLsizei bufSize,
1873                                           GLsizei *length,
1874                                           GLuint *params)
1875 {
1876     if (!context->getExtensions().disjointTimerQuery &&
1877         !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1878     {
1879         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1880         return false;
1881     }
1882 
1883     if (!ValidateRobustEntryPoint(context, bufSize))
1884     {
1885         return false;
1886     }
1887 
1888     if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1889     {
1890         return false;
1891     }
1892 
1893     if (!ValidateRobustBufferSize(context, bufSize, *length))
1894     {
1895         return false;
1896     }
1897 
1898     return true;
1899 }
1900 
ValidateGetQueryObjecti64vEXT(Context * context,GLuint id,GLenum pname,GLint64 * params)1901 bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1902 {
1903     if (!context->getExtensions().disjointTimerQuery)
1904     {
1905         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1906         return false;
1907     }
1908     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1909 }
1910 
ValidateGetQueryObjecti64vRobustANGLE(Context * context,GLuint id,GLenum pname,GLsizei bufSize,GLsizei * length,GLint64 * params)1911 bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1912                                            GLuint id,
1913                                            GLenum pname,
1914                                            GLsizei bufSize,
1915                                            GLsizei *length,
1916                                            GLint64 *params)
1917 {
1918     if (!context->getExtensions().disjointTimerQuery)
1919     {
1920         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1921         return false;
1922     }
1923 
1924     if (!ValidateRobustEntryPoint(context, bufSize))
1925     {
1926         return false;
1927     }
1928 
1929     if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1930     {
1931         return false;
1932     }
1933 
1934     if (!ValidateRobustBufferSize(context, bufSize, *length))
1935     {
1936         return false;
1937     }
1938 
1939     return true;
1940 }
1941 
ValidateGetQueryObjectui64vEXT(Context * context,GLuint id,GLenum pname,GLuint64 * params)1942 bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1943 {
1944     if (!context->getExtensions().disjointTimerQuery)
1945     {
1946         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1947         return false;
1948     }
1949     return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1950 }
1951 
ValidateGetQueryObjectui64vRobustANGLE(Context * context,GLuint id,GLenum pname,GLsizei bufSize,GLsizei * length,GLuint64 * params)1952 bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1953                                             GLuint id,
1954                                             GLenum pname,
1955                                             GLsizei bufSize,
1956                                             GLsizei *length,
1957                                             GLuint64 *params)
1958 {
1959     if (!context->getExtensions().disjointTimerQuery)
1960     {
1961         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
1962         return false;
1963     }
1964 
1965     if (!ValidateRobustEntryPoint(context, bufSize))
1966     {
1967         return false;
1968     }
1969 
1970     if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1971     {
1972         return false;
1973     }
1974 
1975     if (!ValidateRobustBufferSize(context, bufSize, *length))
1976     {
1977         return false;
1978     }
1979 
1980     return true;
1981 }
1982 
ValidateUniformCommonBase(ValidationContext * context,gl::Program * program,GLint location,GLsizei count,const LinkedUniform ** uniformOut)1983 bool ValidateUniformCommonBase(ValidationContext *context,
1984                                gl::Program *program,
1985                                GLint location,
1986                                GLsizei count,
1987                                const LinkedUniform **uniformOut)
1988 {
1989     // TODO(Jiajia): Add image uniform check in future.
1990     if (count < 0)
1991     {
1992         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
1993         return false;
1994     }
1995 
1996     if (!program)
1997     {
1998         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1999         return false;
2000     }
2001 
2002     if (!program->isLinked())
2003     {
2004         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2005         return false;
2006     }
2007 
2008     if (location == -1)
2009     {
2010         // Silently ignore the uniform command
2011         return false;
2012     }
2013 
2014     const auto &uniformLocations = program->getUniformLocations();
2015     size_t castedLocation        = static_cast<size_t>(location);
2016     if (castedLocation >= uniformLocations.size())
2017     {
2018         context->handleError(InvalidOperation() << "Invalid uniform location");
2019         return false;
2020     }
2021 
2022     const auto &uniformLocation = uniformLocations[castedLocation];
2023     if (uniformLocation.ignored)
2024     {
2025         // Silently ignore the uniform command
2026         return false;
2027     }
2028 
2029     if (!uniformLocation.used())
2030     {
2031         context->handleError(InvalidOperation());
2032         return false;
2033     }
2034 
2035     const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2036 
2037     // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2038     if (!uniform.isArray() && count > 1)
2039     {
2040         context->handleError(InvalidOperation());
2041         return false;
2042     }
2043 
2044     *uniformOut = &uniform;
2045     return true;
2046 }
2047 
ValidateUniform1ivValue(ValidationContext * context,GLenum uniformType,GLsizei count,const GLint * value)2048 bool ValidateUniform1ivValue(ValidationContext *context,
2049                              GLenum uniformType,
2050                              GLsizei count,
2051                              const GLint *value)
2052 {
2053     // Value type is GL_INT, because we only get here from glUniform1i{v}.
2054     // It is compatible with INT or BOOL.
2055     // Do these cheap tests first, for a little extra speed.
2056     if (GL_INT == uniformType || GL_BOOL == uniformType)
2057     {
2058         return true;
2059     }
2060 
2061     if (IsSamplerType(uniformType))
2062     {
2063         // Check that the values are in range.
2064         const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2065         for (GLsizei i = 0; i < count; ++i)
2066         {
2067             if (value[i] < 0 || value[i] >= max)
2068             {
2069                 context->handleError(InvalidValue() << "sampler uniform value out of range");
2070                 return false;
2071             }
2072         }
2073         return true;
2074     }
2075 
2076     context->handleError(InvalidOperation() << "wrong type of value for uniform");
2077     return false;
2078 }
2079 
ValidateUniformValue(ValidationContext * context,GLenum valueType,GLenum uniformType)2080 bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2081 {
2082     // Check that the value type is compatible with uniform type.
2083     // Do the cheaper test first, for a little extra speed.
2084     if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2085     {
2086         return true;
2087     }
2088 
2089     ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2090     return false;
2091 }
2092 
ValidateUniformMatrixValue(ValidationContext * context,GLenum valueType,GLenum uniformType)2093 bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2094 {
2095     // Check that the value type is compatible with uniform type.
2096     if (valueType == uniformType)
2097     {
2098         return true;
2099     }
2100 
2101     context->handleError(InvalidOperation() << "wrong type of value for uniform");
2102     return false;
2103 }
2104 
ValidateUniform(ValidationContext * context,GLenum valueType,GLint location,GLsizei count)2105 bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
2106 {
2107     const LinkedUniform *uniform = nullptr;
2108     gl::Program *programObject   = context->getGLState().getProgram();
2109     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2110            ValidateUniformValue(context, valueType, uniform->type);
2111 }
2112 
ValidateUniform1iv(ValidationContext * context,GLint location,GLsizei count,const GLint * value)2113 bool ValidateUniform1iv(ValidationContext *context,
2114                         GLint location,
2115                         GLsizei count,
2116                         const GLint *value)
2117 {
2118     const LinkedUniform *uniform = nullptr;
2119     gl::Program *programObject   = context->getGLState().getProgram();
2120     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2121            ValidateUniform1ivValue(context, uniform->type, count, value);
2122 }
2123 
ValidateUniformMatrix(ValidationContext * context,GLenum valueType,GLint location,GLsizei count,GLboolean transpose)2124 bool ValidateUniformMatrix(ValidationContext *context,
2125                            GLenum valueType,
2126                            GLint location,
2127                            GLsizei count,
2128                            GLboolean transpose)
2129 {
2130     if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
2131     {
2132         context->handleError(InvalidValue());
2133         return false;
2134     }
2135 
2136     const LinkedUniform *uniform = nullptr;
2137     gl::Program *programObject   = context->getGLState().getProgram();
2138     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139            ValidateUniformMatrixValue(context, valueType, uniform->type);
2140 }
2141 
ValidateStateQuery(ValidationContext * context,GLenum pname,GLenum * nativeType,unsigned int * numParams)2142 bool ValidateStateQuery(ValidationContext *context,
2143                         GLenum pname,
2144                         GLenum *nativeType,
2145                         unsigned int *numParams)
2146 {
2147     if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2148     {
2149         context->handleError(InvalidEnum());
2150         return false;
2151     }
2152 
2153     const Caps &caps = context->getCaps();
2154 
2155     if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2156     {
2157         unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2158 
2159         if (colorAttachment >= caps.maxDrawBuffers)
2160         {
2161             context->handleError(InvalidOperation());
2162             return false;
2163         }
2164     }
2165 
2166     switch (pname)
2167     {
2168         case GL_TEXTURE_BINDING_2D:
2169         case GL_TEXTURE_BINDING_CUBE_MAP:
2170         case GL_TEXTURE_BINDING_3D:
2171         case GL_TEXTURE_BINDING_2D_ARRAY:
2172         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
2173             break;
2174         case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2175             if (!context->getExtensions().textureRectangle)
2176             {
2177                 context->handleError(InvalidEnum()
2178                                      << "ANGLE_texture_rectangle extension not present");
2179                 return false;
2180             }
2181             break;
2182         case GL_TEXTURE_BINDING_EXTERNAL_OES:
2183             if (!context->getExtensions().eglStreamConsumerExternal &&
2184                 !context->getExtensions().eglImageExternal)
2185             {
2186                 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2187                                                       "nor GL_OES_EGL_image_external "
2188                                                       "extensions enabled");
2189                 return false;
2190             }
2191             break;
2192 
2193         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2194         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2195         {
2196             if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2197                 GL_FRAMEBUFFER_COMPLETE)
2198             {
2199                 context->handleError(InvalidOperation());
2200                 return false;
2201             }
2202 
2203             const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2204             ASSERT(framebuffer);
2205 
2206             if (framebuffer->getReadBufferState() == GL_NONE)
2207             {
2208                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
2209                 return false;
2210             }
2211 
2212             const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
2213             if (!attachment)
2214             {
2215                 context->handleError(InvalidOperation());
2216                 return false;
2217             }
2218         }
2219         break;
2220 
2221         default:
2222             break;
2223     }
2224 
2225     // pname is valid, but there are no parameters to return
2226     if (*numParams == 0)
2227     {
2228         return false;
2229     }
2230 
2231     return true;
2232 }
2233 
ValidateRobustStateQuery(ValidationContext * context,GLenum pname,GLsizei bufSize,GLenum * nativeType,unsigned int * numParams)2234 bool ValidateRobustStateQuery(ValidationContext *context,
2235                               GLenum pname,
2236                               GLsizei bufSize,
2237                               GLenum *nativeType,
2238                               unsigned int *numParams)
2239 {
2240     if (!ValidateRobustEntryPoint(context, bufSize))
2241     {
2242         return false;
2243     }
2244 
2245     if (!ValidateStateQuery(context, pname, nativeType, numParams))
2246     {
2247         return false;
2248     }
2249 
2250     if (!ValidateRobustBufferSize(context, bufSize, *numParams))
2251     {
2252         return false;
2253     }
2254 
2255     return true;
2256 }
2257 
ValidateCopyTexImageParametersBase(ValidationContext * context,GLenum 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)2258 bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2259                                         GLenum target,
2260                                         GLint level,
2261                                         GLenum internalformat,
2262                                         bool isSubImage,
2263                                         GLint xoffset,
2264                                         GLint yoffset,
2265                                         GLint zoffset,
2266                                         GLint x,
2267                                         GLint y,
2268                                         GLsizei width,
2269                                         GLsizei height,
2270                                         GLint border,
2271                                         Format *textureFormatOut)
2272 {
2273     if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2274     {
2275         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2276         return false;
2277     }
2278 
2279     if (width < 0 || height < 0)
2280     {
2281         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
2282         return false;
2283     }
2284 
2285     if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2286         std::numeric_limits<GLsizei>::max() - yoffset < height)
2287     {
2288         context->handleError(InvalidValue());
2289         return false;
2290     }
2291 
2292     if (border != 0)
2293     {
2294         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
2295         return false;
2296     }
2297 
2298     if (!ValidMipLevel(context, target, level))
2299     {
2300         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
2301         return false;
2302     }
2303 
2304     const auto &state    = context->getGLState();
2305     Framebuffer *readFramebuffer = state.getReadFramebuffer();
2306     if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
2307     {
2308         context->handleError(InvalidFramebufferOperation());
2309         return false;
2310     }
2311 
2312     if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
2313     {
2314         context->handleError(InvalidOperation());
2315         return false;
2316     }
2317 
2318     if (readFramebuffer->getReadBufferState() == GL_NONE)
2319     {
2320         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
2321         return false;
2322     }
2323 
2324     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2325     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
2326     // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2327     // situation is an application error that would lead to a crash in ANGLE.
2328     const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2329     if (source == nullptr)
2330     {
2331         ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
2332         return false;
2333     }
2334 
2335     // ANGLE_multiview spec, Revision 1:
2336     // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2337     // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2338     // is not NONE.
2339     if (source->getMultiviewLayout() != GL_NONE)
2340     {
2341         context->handleError(InvalidFramebufferOperation()
2342                              << "The active read framebuffer object has multiview attachments.");
2343         return false;
2344     }
2345 
2346     const gl::Caps &caps = context->getCaps();
2347 
2348     GLuint maxDimension = 0;
2349     switch (target)
2350     {
2351         case GL_TEXTURE_2D:
2352             maxDimension = caps.max2DTextureSize;
2353             break;
2354 
2355         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2356         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2357         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2358         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2359         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2360         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2361             maxDimension = caps.maxCubeMapTextureSize;
2362             break;
2363 
2364         case GL_TEXTURE_RECTANGLE_ANGLE:
2365             maxDimension = caps.maxRectangleTextureSize;
2366             break;
2367 
2368         case GL_TEXTURE_2D_ARRAY:
2369             maxDimension = caps.max2DTextureSize;
2370             break;
2371 
2372         case GL_TEXTURE_3D:
2373             maxDimension = caps.max3DTextureSize;
2374             break;
2375 
2376         default:
2377             context->handleError(InvalidEnum());
2378             return false;
2379     }
2380 
2381     gl::Texture *texture =
2382         state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
2383     if (!texture)
2384     {
2385         ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
2386         return false;
2387     }
2388 
2389     if (texture->getImmutableFormat() && !isSubImage)
2390     {
2391         context->handleError(InvalidOperation());
2392         return false;
2393     }
2394 
2395     const gl::InternalFormat &formatInfo =
2396         isSubImage ? *texture->getFormat(target, level).info
2397                    : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
2398 
2399     if (formatInfo.depthBits > 0 || formatInfo.compressed)
2400     {
2401         context->handleError(InvalidOperation());
2402         return false;
2403     }
2404 
2405     if (isSubImage)
2406     {
2407         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2408             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2409             static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
2410         {
2411             context->handleError(InvalidValue());
2412             return false;
2413         }
2414     }
2415     else
2416     {
2417         if (IsCubeMapTextureTarget(target) && width != height)
2418         {
2419             ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
2420             return false;
2421         }
2422 
2423         if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
2424         {
2425             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
2426             return false;
2427         }
2428 
2429         int maxLevelDimension = (maxDimension >> level);
2430         if (static_cast<int>(width) > maxLevelDimension ||
2431             static_cast<int>(height) > maxLevelDimension)
2432         {
2433             ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
2434             return false;
2435         }
2436     }
2437 
2438     if (textureFormatOut)
2439     {
2440         *textureFormatOut = texture->getFormat(target, level);
2441     }
2442 
2443     // Detect texture copying feedback loops for WebGL.
2444     if (context->getExtensions().webglCompatibility)
2445     {
2446         if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
2447         {
2448             ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2449             return false;
2450         }
2451     }
2452 
2453     return true;
2454 }
2455 
ValidateDrawBase(ValidationContext * context,GLenum mode,GLsizei count)2456 bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
2457 {
2458     switch (mode)
2459     {
2460         case GL_POINTS:
2461         case GL_LINES:
2462         case GL_LINE_LOOP:
2463         case GL_LINE_STRIP:
2464         case GL_TRIANGLES:
2465         case GL_TRIANGLE_STRIP:
2466         case GL_TRIANGLE_FAN:
2467             break;
2468         default:
2469             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
2470             return false;
2471     }
2472 
2473     if (count < 0)
2474     {
2475         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2476         return false;
2477     }
2478 
2479     const State &state = context->getGLState();
2480 
2481     const Extensions &extensions = context->getExtensions();
2482 
2483     // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2484     // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2485     // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2486     if (!extensions.webglCompatibility)
2487     {
2488         // Check for mapped buffers
2489         // TODO(jmadill): Optimize this check for non - WebGL contexts.
2490         if (state.hasMappedBuffer(BufferBinding::Array))
2491         {
2492             context->handleError(InvalidOperation());
2493             return false;
2494         }
2495     }
2496 
2497     // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2498     // Section 6.10 of the WebGL 1.0 spec.
2499     Framebuffer *framebuffer = state.getDrawFramebuffer();
2500     if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2501     {
2502         const FramebufferAttachment *dsAttachment =
2503             framebuffer->getStencilOrDepthStencilAttachment();
2504         GLuint stencilBits                = dsAttachment ? dsAttachment->getStencilSize() : 0;
2505         GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2506         const DepthStencilState &depthStencilState = state.getDepthStencilState();
2507 
2508         bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2509         bool differentWritemasks =
2510             (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2511             (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2512         bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2513                               (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2514 
2515         if (differentRefs || differentWritemasks || differentMasks)
2516         {
2517             if (!extensions.webglCompatibility)
2518             {
2519                 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2520                          "writemasks, reference values, or stencil mask values.";
2521             }
2522             ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2523             return false;
2524         }
2525     }
2526 
2527     if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
2528     {
2529         context->handleError(InvalidFramebufferOperation());
2530         return false;
2531     }
2532 
2533     gl::Program *program = state.getProgram();
2534     if (!program)
2535     {
2536         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2537         return false;
2538     }
2539 
2540     // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2541     // vertex shader stage or fragment shader stage is a undefined behaviour.
2542     // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2543     // produce undefined result.
2544     if (program->isLinked() &&
2545         (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader()))
2546     {
2547         context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2548                                                    "vertex shader stage or fragment shader stage.");
2549         return false;
2550     }
2551 
2552     if (!program->validateSamplers(nullptr, context->getCaps()))
2553     {
2554         context->handleError(InvalidOperation());
2555         return false;
2556     }
2557 
2558     if (extensions.multiview)
2559     {
2560         const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
2561         const int framebufferNumViews = framebuffer->getNumViews();
2562         if (framebufferNumViews != programNumViews)
2563         {
2564             context->handleError(InvalidOperation() << "The number of views in the active program "
2565                                                        "and draw framebuffer does not match.");
2566             return false;
2567         }
2568 
2569         const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2570         if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2571             framebufferNumViews > 1)
2572         {
2573             context->handleError(InvalidOperation()
2574                                  << "There is an active transform feedback object "
2575                                     "when the number of views in the active draw "
2576                                     "framebuffer is greater than 1.");
2577             return false;
2578         }
2579 
2580         if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2581             state.isQueryActive(GL_TIME_ELAPSED_EXT))
2582         {
2583             context->handleError(InvalidOperation() << "There is an active query for target "
2584                                                        "GL_TIME_ELAPSED_EXT when the number of "
2585                                                        "views in the active draw framebuffer is "
2586                                                        "greater than 1.");
2587             return false;
2588         }
2589     }
2590 
2591     // Uniform buffer validation
2592     for (unsigned int uniformBlockIndex = 0;
2593          uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2594     {
2595         const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2596         GLuint blockBinding                  = program->getUniformBlockBinding(uniformBlockIndex);
2597         const OffsetBindingPointer<Buffer> &uniformBuffer =
2598             state.getIndexedUniformBuffer(blockBinding);
2599 
2600         if (uniformBuffer.get() == nullptr)
2601         {
2602             // undefined behaviour
2603             context->handleError(
2604                 InvalidOperation()
2605                 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2606             return false;
2607         }
2608 
2609         size_t uniformBufferSize = uniformBuffer.getSize();
2610         if (uniformBufferSize == 0)
2611         {
2612             // Bind the whole buffer.
2613             uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
2614         }
2615 
2616         if (uniformBufferSize < uniformBlock.dataSize)
2617         {
2618             // undefined behaviour
2619             context->handleError(
2620                 InvalidOperation()
2621                 << "It is undefined behaviour to use a uniform buffer that is too small.");
2622             return false;
2623         }
2624     }
2625 
2626     // Do some additonal WebGL-specific validation
2627     if (extensions.webglCompatibility)
2628     {
2629         // Detect rendering feedback loops for WebGL.
2630         if (framebuffer->formsRenderingFeedbackLoopWith(state))
2631         {
2632             ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2633             return false;
2634         }
2635 
2636         // Detect that the vertex shader input types match the attribute types
2637         if (!ValidateVertexShaderAttributeTypeMatch(context))
2638         {
2639             return false;
2640         }
2641 
2642         // Detect that the color buffer types match the fragment shader output types
2643         if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2644         {
2645             return false;
2646         }
2647     }
2648 
2649     // No-op if zero count
2650     return (count > 0);
2651 }
2652 
ValidateDrawArraysCommon(ValidationContext * context,GLenum mode,GLint first,GLsizei count,GLsizei primcount)2653 bool ValidateDrawArraysCommon(ValidationContext *context,
2654                               GLenum mode,
2655                               GLint first,
2656                               GLsizei count,
2657                               GLsizei primcount)
2658 {
2659     if (first < 0)
2660     {
2661         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
2662         return false;
2663     }
2664 
2665     const State &state                          = context->getGLState();
2666     gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
2667     if (curTransformFeedback && curTransformFeedback->isActive() &&
2668         !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
2669     {
2670         // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2671         // that does not match the current transform feedback object's draw mode (if transform
2672         // feedback
2673         // is active), (3.0.2, section 2.14, pg 86)
2674         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2675         return false;
2676     }
2677 
2678     if (!ValidateDrawBase(context, mode, count))
2679     {
2680         return false;
2681     }
2682 
2683     // Check the computation of maxVertex doesn't overflow.
2684     // - first < 0 or count < 0 have been checked as an error condition
2685     // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2686     // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2687     ASSERT(count > 0 && first >= 0);
2688     int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2689     if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2690     {
2691         ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2692         return false;
2693     }
2694 
2695     if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2696     {
2697         return false;
2698     }
2699 
2700     return true;
2701 }
2702 
ValidateDrawArraysInstancedANGLE(Context * context,GLenum mode,GLint first,GLsizei count,GLsizei primcount)2703 bool ValidateDrawArraysInstancedANGLE(Context *context,
2704                                       GLenum mode,
2705                                       GLint first,
2706                                       GLsizei count,
2707                                       GLsizei primcount)
2708 {
2709     if (!context->getExtensions().instancedArrays)
2710     {
2711         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2712         return false;
2713     }
2714 
2715     if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
2716     {
2717         return false;
2718     }
2719 
2720     return ValidateDrawInstancedANGLE(context);
2721 }
2722 
ValidateDrawElementsBase(ValidationContext * context,GLenum type)2723 bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
2724 {
2725     switch (type)
2726     {
2727         case GL_UNSIGNED_BYTE:
2728         case GL_UNSIGNED_SHORT:
2729             break;
2730         case GL_UNSIGNED_INT:
2731             if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2732             {
2733                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
2734                 return false;
2735             }
2736             break;
2737         default:
2738             ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
2739             return false;
2740     }
2741 
2742     const State &state = context->getGLState();
2743 
2744     gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
2745     if (curTransformFeedback && curTransformFeedback->isActive() &&
2746         !curTransformFeedback->isPaused())
2747     {
2748         // It is an invalid operation to call DrawElements, DrawRangeElements or
2749         // DrawElementsInstanced
2750         // while transform feedback is active, (3.0.2, section 2.14, pg 86)
2751         context->handleError(InvalidOperation());
2752         return false;
2753     }
2754 
2755     return true;
2756 }
2757 
ValidateDrawElementsCommon(ValidationContext * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount)2758 bool ValidateDrawElementsCommon(ValidationContext *context,
2759                                 GLenum mode,
2760                                 GLsizei count,
2761                                 GLenum type,
2762                                 const void *indices,
2763                                 GLsizei primcount)
2764 {
2765     if (!ValidateDrawElementsBase(context, type))
2766         return false;
2767 
2768     const State &state = context->getGLState();
2769 
2770     if (!ValidateDrawBase(context, mode, count))
2771     {
2772         return false;
2773     }
2774 
2775     // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2776     // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2777     // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2778     if (!context->getExtensions().webglCompatibility)
2779     {
2780         // Check for mapped buffers
2781         // TODO(jmadill): Optimize this check for non - WebGL contexts.
2782         if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
2783         {
2784             context->handleError(InvalidOperation() << "Index buffer is mapped.");
2785             return false;
2786         }
2787     }
2788 
2789     const gl::VertexArray *vao     = state.getVertexArray();
2790     gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
2791 
2792     GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2793 
2794     if (context->getExtensions().webglCompatibility)
2795     {
2796         ASSERT(isPow2(typeBytes) && typeBytes > 0);
2797         if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2798         {
2799             // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2800             // The offset arguments to drawElements and [...], must be a multiple of the size of the
2801             // data type passed to the call, or an INVALID_OPERATION error is generated.
2802             ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
2803             return false;
2804         }
2805 
2806         // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2807         // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2808         // error is generated.
2809         if (reinterpret_cast<intptr_t>(indices) < 0)
2810         {
2811             ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2812             return false;
2813         }
2814     }
2815 
2816     if (context->getExtensions().webglCompatibility ||
2817         !context->getGLState().areClientArraysEnabled())
2818     {
2819         if (!elementArrayBuffer && count > 0)
2820         {
2821             // [WebGL 1.0] Section 6.2 No Client Side Arrays
2822             // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2823             // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2824             ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
2825             return false;
2826         }
2827     }
2828 
2829     if (count > 0)
2830     {
2831         if (elementArrayBuffer)
2832         {
2833             // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2834             // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2835             static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2836             constexpr uint64_t kMaxTypeSize = 8;
2837             constexpr uint64_t kIntMax      = std::numeric_limits<int>::max();
2838             constexpr uint64_t kUint64Max   = std::numeric_limits<uint64_t>::max();
2839             static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2840 
2841             uint64_t typeSize     = typeBytes;
2842             uint64_t elementCount = static_cast<uint64_t>(count);
2843             ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2844 
2845             // Doing the multiplication here is overflow-safe
2846             uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2847 
2848             // The offset can be any value, check for overflows
2849             uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2850             if (elementDataSizeNoOffset > kUint64Max - offset)
2851             {
2852                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2853                 return false;
2854             }
2855 
2856             uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2857             if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
2858             {
2859                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2860                 return false;
2861             }
2862 
2863             ASSERT(isPow2(typeSize) && typeSize > 0);
2864             if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2865             {
2866                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2867                 return false;
2868             }
2869         }
2870         else if (!indices)
2871         {
2872             // This is an application error that would normally result in a crash,
2873             // but we catch it and return an error
2874             context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2875             return false;
2876         }
2877     }
2878 
2879     if (context->getExtensions().robustBufferAccessBehavior)
2880     {
2881         // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2882         // access is enabled.
2883         if (!ValidateDrawAttribs(context, primcount, 0, 1))
2884         {
2885             return false;
2886         }
2887     }
2888     else
2889     {
2890         // Use the parameter buffer to retrieve and cache the index range.
2891         const auto &params        = context->getParams<HasIndexRange>();
2892         const auto &indexRangeOpt = params.getIndexRange();
2893         if (!indexRangeOpt.valid())
2894         {
2895             // Unexpected error.
2896             return false;
2897         }
2898 
2899         // If we use an index greater than our maximum supported index range, return an error.
2900         // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2901         // return an error if possible here.
2902         if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2903         {
2904             ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2905             return false;
2906         }
2907 
2908         if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2909                                  static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2910         {
2911             return false;
2912         }
2913 
2914         // No op if there are no real indices in the index data (all are primitive restart).
2915         return (indexRangeOpt.value().vertexIndexCount > 0);
2916     }
2917 
2918     return true;
2919 }
2920 
ValidateDrawElementsInstancedCommon(ValidationContext * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount)2921 bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2922                                          GLenum mode,
2923                                          GLsizei count,
2924                                          GLenum type,
2925                                          const void *indices,
2926                                          GLsizei primcount)
2927 {
2928     return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
2929 }
2930 
ValidateDrawElementsInstancedANGLE(Context * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei primcount)2931 bool ValidateDrawElementsInstancedANGLE(Context *context,
2932                                         GLenum mode,
2933                                         GLsizei count,
2934                                         GLenum type,
2935                                         const void *indices,
2936                                         GLsizei primcount)
2937 {
2938     if (!context->getExtensions().instancedArrays)
2939     {
2940         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2941         return false;
2942     }
2943 
2944     if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
2945     {
2946         return false;
2947     }
2948 
2949     return ValidateDrawInstancedANGLE(context);
2950 }
2951 
ValidateFramebufferTextureBase(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level)2952 bool ValidateFramebufferTextureBase(Context *context,
2953                                     GLenum target,
2954                                     GLenum attachment,
2955                                     GLuint texture,
2956                                     GLint level)
2957 {
2958     if (!ValidFramebufferTarget(context, target))
2959     {
2960         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
2961         return false;
2962     }
2963 
2964     if (!ValidateAttachmentTarget(context, attachment))
2965     {
2966         return false;
2967     }
2968 
2969     if (texture != 0)
2970     {
2971         gl::Texture *tex = context->getTexture(texture);
2972 
2973         if (tex == NULL)
2974         {
2975             context->handleError(InvalidOperation());
2976             return false;
2977         }
2978 
2979         if (level < 0)
2980         {
2981             context->handleError(InvalidValue());
2982             return false;
2983         }
2984     }
2985 
2986     const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
2987     ASSERT(framebuffer);
2988 
2989     if (framebuffer->id() == 0)
2990     {
2991         ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
2992         return false;
2993     }
2994 
2995     return true;
2996 }
2997 
ValidateGetUniformBase(Context * context,GLuint program,GLint location)2998 bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
2999 {
3000     if (program == 0)
3001     {
3002         context->handleError(InvalidValue());
3003         return false;
3004     }
3005 
3006     gl::Program *programObject = GetValidProgram(context, program);
3007     if (!programObject)
3008     {
3009         return false;
3010     }
3011 
3012     if (!programObject || !programObject->isLinked())
3013     {
3014         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3015         return false;
3016     }
3017 
3018     if (!programObject->isValidUniformLocation(location))
3019     {
3020         context->handleError(InvalidOperation());
3021         return false;
3022     }
3023 
3024     return true;
3025 }
3026 
ValidateSizedGetUniform(Context * context,GLuint program,GLint location,GLsizei bufSize,GLsizei * length)3027 static bool ValidateSizedGetUniform(Context *context,
3028                                     GLuint program,
3029                                     GLint location,
3030                                     GLsizei bufSize,
3031                                     GLsizei *length)
3032 {
3033     if (length)
3034     {
3035         *length = 0;
3036     }
3037 
3038     if (!ValidateGetUniformBase(context, program, location))
3039     {
3040         return false;
3041     }
3042 
3043     if (bufSize < 0)
3044     {
3045         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3046         return false;
3047     }
3048 
3049     gl::Program *programObject = context->getProgram(program);
3050     ASSERT(programObject);
3051 
3052     // sized queries -- ensure the provided buffer is large enough
3053     const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3054     size_t requiredBytes         = VariableExternalSize(uniform.type);
3055     if (static_cast<size_t>(bufSize) < requiredBytes)
3056     {
3057         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3058         return false;
3059     }
3060 
3061     if (length)
3062     {
3063         *length = VariableComponentCount(uniform.type);
3064     }
3065 
3066     return true;
3067 }
3068 
ValidateGetnUniformfvEXT(Context * context,GLuint program,GLint location,GLsizei bufSize,GLfloat * params)3069 bool ValidateGetnUniformfvEXT(Context *context,
3070                               GLuint program,
3071                               GLint location,
3072                               GLsizei bufSize,
3073                               GLfloat *params)
3074 {
3075     return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3076 }
3077 
ValidateGetnUniformivEXT(Context * context,GLuint program,GLint location,GLsizei bufSize,GLint * params)3078 bool ValidateGetnUniformivEXT(Context *context,
3079                               GLuint program,
3080                               GLint location,
3081                               GLsizei bufSize,
3082                               GLint *params)
3083 {
3084     return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3085 }
3086 
ValidateGetUniformfvRobustANGLE(Context * context,GLuint program,GLint location,GLsizei bufSize,GLsizei * length,GLfloat * params)3087 bool ValidateGetUniformfvRobustANGLE(Context *context,
3088                                      GLuint program,
3089                                      GLint location,
3090                                      GLsizei bufSize,
3091                                      GLsizei *length,
3092                                      GLfloat *params)
3093 {
3094     if (!ValidateRobustEntryPoint(context, bufSize))
3095     {
3096         return false;
3097     }
3098 
3099     // bufSize is validated in ValidateSizedGetUniform
3100     return ValidateSizedGetUniform(context, program, location, bufSize, length);
3101 }
3102 
ValidateGetUniformivRobustANGLE(Context * context,GLuint program,GLint location,GLsizei bufSize,GLsizei * length,GLint * params)3103 bool ValidateGetUniformivRobustANGLE(Context *context,
3104                                      GLuint program,
3105                                      GLint location,
3106                                      GLsizei bufSize,
3107                                      GLsizei *length,
3108                                      GLint *params)
3109 {
3110     if (!ValidateRobustEntryPoint(context, bufSize))
3111     {
3112         return false;
3113     }
3114 
3115     // bufSize is validated in ValidateSizedGetUniform
3116     return ValidateSizedGetUniform(context, program, location, bufSize, length);
3117 }
3118 
ValidateGetUniformuivRobustANGLE(Context * context,GLuint program,GLint location,GLsizei bufSize,GLsizei * length,GLuint * params)3119 bool ValidateGetUniformuivRobustANGLE(Context *context,
3120                                       GLuint program,
3121                                       GLint location,
3122                                       GLsizei bufSize,
3123                                       GLsizei *length,
3124                                       GLuint *params)
3125 {
3126     if (!ValidateRobustEntryPoint(context, bufSize))
3127     {
3128         return false;
3129     }
3130 
3131     if (context->getClientMajorVersion() < 3)
3132     {
3133         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3134         return false;
3135     }
3136 
3137     // bufSize is validated in ValidateSizedGetUniform
3138     return ValidateSizedGetUniform(context, program, location, bufSize, length);
3139 }
3140 
ValidateDiscardFramebufferBase(Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,bool defaultFramebuffer)3141 bool ValidateDiscardFramebufferBase(Context *context,
3142                                     GLenum target,
3143                                     GLsizei numAttachments,
3144                                     const GLenum *attachments,
3145                                     bool defaultFramebuffer)
3146 {
3147     if (numAttachments < 0)
3148     {
3149         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
3150         return false;
3151     }
3152 
3153     for (GLsizei i = 0; i < numAttachments; ++i)
3154     {
3155         if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
3156         {
3157             if (defaultFramebuffer)
3158             {
3159                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
3160                 return false;
3161             }
3162 
3163             if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3164             {
3165                 context->handleError(InvalidOperation() << "Requested color attachment is "
3166                                                            "greater than the maximum supported "
3167                                                            "color attachments");
3168                 return false;
3169             }
3170         }
3171         else
3172         {
3173             switch (attachments[i])
3174             {
3175                 case GL_DEPTH_ATTACHMENT:
3176                 case GL_STENCIL_ATTACHMENT:
3177                 case GL_DEPTH_STENCIL_ATTACHMENT:
3178                     if (defaultFramebuffer)
3179                     {
3180                         ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3181                                              DefaultFramebufferInvalidAttachment);
3182                         return false;
3183                     }
3184                     break;
3185                 case GL_COLOR:
3186                 case GL_DEPTH:
3187                 case GL_STENCIL:
3188                     if (!defaultFramebuffer)
3189                     {
3190                         ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3191                                              DefaultFramebufferInvalidAttachment);
3192                         return false;
3193                     }
3194                     break;
3195                 default:
3196                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3197                     return false;
3198             }
3199         }
3200     }
3201 
3202     return true;
3203 }
3204 
ValidateInsertEventMarkerEXT(Context * context,GLsizei length,const char * marker)3205 bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3206 {
3207     // Note that debug marker calls must not set error state
3208 
3209     if (length < 0)
3210     {
3211         return false;
3212     }
3213 
3214     if (marker == nullptr)
3215     {
3216         return false;
3217     }
3218 
3219     return true;
3220 }
3221 
ValidatePushGroupMarkerEXT(Context * context,GLsizei length,const char * marker)3222 bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3223 {
3224     // Note that debug marker calls must not set error state
3225 
3226     if (length < 0)
3227     {
3228         return false;
3229     }
3230 
3231     if (length > 0 && marker == nullptr)
3232     {
3233         return false;
3234     }
3235 
3236     return true;
3237 }
3238 
ValidateEGLImageTargetTexture2DOES(Context * context,GLenum target,egl::Image * image)3239 bool ValidateEGLImageTargetTexture2DOES(Context *context,
3240                                         GLenum target,
3241                                         egl::Image *image)
3242 {
3243     if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3244     {
3245         context->handleError(InvalidOperation());
3246         return false;
3247     }
3248 
3249     switch (target)
3250     {
3251         case GL_TEXTURE_2D:
3252             if (!context->getExtensions().eglImage)
3253             {
3254                 context->handleError(InvalidEnum()
3255                                      << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
3256             }
3257             break;
3258 
3259         case GL_TEXTURE_EXTERNAL_OES:
3260             if (!context->getExtensions().eglImageExternal)
3261             {
3262                 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3263                                                       "requires GL_OES_EGL_image_external.");
3264             }
3265             break;
3266 
3267         default:
3268             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
3269             return false;
3270     }
3271 
3272     ASSERT(context->getCurrentDisplay());
3273     if (!context->getCurrentDisplay()->isValidImage(image))
3274     {
3275         context->handleError(InvalidValue() << "EGL image is not valid.");
3276         return false;
3277     }
3278 
3279     if (image->getSamples() > 0)
3280     {
3281         context->handleError(InvalidOperation()
3282                              << "cannot create a 2D texture from a multisampled EGL image.");
3283         return false;
3284     }
3285 
3286     const TextureCaps &textureCaps =
3287         context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
3288     if (!textureCaps.texturable)
3289     {
3290         context->handleError(InvalidOperation()
3291                              << "EGL image internal format is not supported as a texture.");
3292         return false;
3293     }
3294 
3295     return true;
3296 }
3297 
ValidateEGLImageTargetRenderbufferStorageOES(Context * context,GLenum target,egl::Image * image)3298 bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3299                                                   GLenum target,
3300                                                   egl::Image *image)
3301 {
3302     if (!context->getExtensions().eglImage)
3303     {
3304         context->handleError(InvalidOperation());
3305         return false;
3306     }
3307 
3308     switch (target)
3309     {
3310         case GL_RENDERBUFFER:
3311             break;
3312 
3313         default:
3314             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
3315             return false;
3316     }
3317 
3318     ASSERT(context->getCurrentDisplay());
3319     if (!context->getCurrentDisplay()->isValidImage(image))
3320     {
3321         context->handleError(InvalidValue() << "EGL image is not valid.");
3322         return false;
3323     }
3324 
3325     const TextureCaps &textureCaps =
3326         context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
3327     if (!textureCaps.renderable)
3328     {
3329         context->handleError(InvalidOperation()
3330                              << "EGL image internal format is not supported as a renderbuffer.");
3331         return false;
3332     }
3333 
3334     return true;
3335 }
3336 
ValidateBindVertexArrayBase(Context * context,GLuint array)3337 bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3338 {
3339     if (!context->isVertexArrayGenerated(array))
3340     {
3341         // The default VAO should always exist
3342         ASSERT(array != 0);
3343         context->handleError(InvalidOperation());
3344         return false;
3345     }
3346 
3347     return true;
3348 }
3349 
ValidateProgramBinaryBase(Context * context,GLuint program,GLenum binaryFormat,const void * binary,GLint length)3350 bool ValidateProgramBinaryBase(Context *context,
3351                                GLuint program,
3352                                GLenum binaryFormat,
3353                                const void *binary,
3354                                GLint length)
3355 {
3356     Program *programObject = GetValidProgram(context, program);
3357     if (programObject == nullptr)
3358     {
3359         return false;
3360     }
3361 
3362     const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3363     if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3364         programBinaryFormats.end())
3365     {
3366         context->handleError(InvalidEnum() << "Program binary format is not valid.");
3367         return false;
3368     }
3369 
3370     if (context->hasActiveTransformFeedback(program))
3371     {
3372         // ES 3.0.4 section 2.15 page 91
3373         context->handleError(InvalidOperation() << "Cannot change program binary while program "
3374                                                    "is associated with an active transform "
3375                                                    "feedback object.");
3376         return false;
3377     }
3378 
3379     return true;
3380 }
3381 
ValidateGetProgramBinaryBase(Context * context,GLuint program,GLsizei bufSize,GLsizei * length,GLenum * binaryFormat,void * binary)3382 bool ValidateGetProgramBinaryBase(Context *context,
3383                                   GLuint program,
3384                                   GLsizei bufSize,
3385                                   GLsizei *length,
3386                                   GLenum *binaryFormat,
3387                                   void *binary)
3388 {
3389     Program *programObject = GetValidProgram(context, program);
3390     if (programObject == nullptr)
3391     {
3392         return false;
3393     }
3394 
3395     if (!programObject->isLinked())
3396     {
3397         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3398         return false;
3399     }
3400 
3401     if (context->getCaps().programBinaryFormats.empty())
3402     {
3403         context->handleError(InvalidOperation() << "No program binary formats supported.");
3404         return false;
3405     }
3406 
3407     return true;
3408 }
3409 
ValidateDrawBuffersBase(ValidationContext * context,GLsizei n,const GLenum * bufs)3410 bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3411 {
3412     // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3413     if (n < 0)
3414     {
3415         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3416         return false;
3417     }
3418     if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3419     {
3420         ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
3421         return false;
3422     }
3423 
3424     ASSERT(context->getGLState().getDrawFramebuffer());
3425     GLuint frameBufferId      = context->getGLState().getDrawFramebuffer()->id();
3426     GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3427 
3428     // This should come first before the check for the default frame buffer
3429     // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3430     // rather than INVALID_OPERATION
3431     for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3432     {
3433         const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3434 
3435         if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
3436             (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3437              bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
3438         {
3439             // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
3440             // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3441             // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3442             // 3.1 is still a bit ambiguous about the error, but future specs are
3443             // expected to clarify that GL_INVALID_ENUM is the correct error.
3444             context->handleError(InvalidEnum() << "Invalid buffer value");
3445             return false;
3446         }
3447         else if (bufs[colorAttachment] >= maxColorAttachment)
3448         {
3449             context->handleError(InvalidOperation()
3450                                  << "Buffer value is greater than MAX_DRAW_BUFFERS");
3451             return false;
3452         }
3453         else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3454                  frameBufferId != 0)
3455         {
3456             // INVALID_OPERATION-GL is bound to buffer and ith argument
3457             // is not COLOR_ATTACHMENTi or NONE
3458             context->handleError(InvalidOperation()
3459                                  << "Ith value does not match COLOR_ATTACHMENTi or NONE");
3460             return false;
3461         }
3462     }
3463 
3464     // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3465     // and n is not 1 or bufs is bound to value other than BACK and NONE
3466     if (frameBufferId == 0)
3467     {
3468         if (n != 1)
3469         {
3470             context->handleError(InvalidOperation()
3471                                  << "n must be 1 when GL is bound to the default framebuffer");
3472             return false;
3473         }
3474 
3475         if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3476         {
3477             context->handleError(
3478                 InvalidOperation()
3479                 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
3480             return false;
3481         }
3482     }
3483 
3484     return true;
3485 }
3486 
ValidateGetBufferPointervBase(Context * context,BufferBinding target,GLenum pname,GLsizei * length,void ** params)3487 bool ValidateGetBufferPointervBase(Context *context,
3488                                    BufferBinding target,
3489                                    GLenum pname,
3490                                    GLsizei *length,
3491                                    void **params)
3492 {
3493     if (length)
3494     {
3495         *length = 0;
3496     }
3497 
3498     if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3499     {
3500         context->handleError(
3501             InvalidOperation()
3502             << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
3503         return false;
3504     }
3505 
3506     if (!ValidBufferType(context, target))
3507     {
3508         context->handleError(InvalidEnum() << "Buffer target not valid");
3509         return false;
3510     }
3511 
3512     switch (pname)
3513     {
3514         case GL_BUFFER_MAP_POINTER:
3515             break;
3516 
3517         default:
3518             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3519             return false;
3520     }
3521 
3522     // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3523     // target bound to zero generate an INVALID_OPERATION error."
3524     // GLES 3.1 section 6.6 explicitly specifies this error.
3525     if (context->getGLState().getTargetBuffer(target) == nullptr)
3526     {
3527         context->handleError(InvalidOperation()
3528                              << "Cannot get pointer for reserved buffer name zero.");
3529         return false;
3530     }
3531 
3532     if (length)
3533     {
3534         *length = 1;
3535     }
3536 
3537     return true;
3538 }
3539 
ValidateUnmapBufferBase(Context * context,BufferBinding target)3540 bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
3541 {
3542     if (!ValidBufferType(context, target))
3543     {
3544         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
3545         return false;
3546     }
3547 
3548     Buffer *buffer = context->getGLState().getTargetBuffer(target);
3549 
3550     if (buffer == nullptr || !buffer->isMapped())
3551     {
3552         context->handleError(InvalidOperation() << "Buffer not mapped.");
3553         return false;
3554     }
3555 
3556     return true;
3557 }
3558 
ValidateMapBufferRangeBase(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3559 bool ValidateMapBufferRangeBase(Context *context,
3560                                 BufferBinding target,
3561                                 GLintptr offset,
3562                                 GLsizeiptr length,
3563                                 GLbitfield access)
3564 {
3565     if (!ValidBufferType(context, target))
3566     {
3567         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
3568         return false;
3569     }
3570 
3571     if (offset < 0)
3572     {
3573         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3574         return false;
3575     }
3576 
3577     if (length < 0)
3578     {
3579         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
3580         return false;
3581     }
3582 
3583     Buffer *buffer = context->getGLState().getTargetBuffer(target);
3584 
3585     if (!buffer)
3586     {
3587         context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
3588         return false;
3589     }
3590 
3591     // Check for buffer overflow
3592     CheckedNumeric<size_t> checkedOffset(offset);
3593     auto checkedSize = checkedOffset + length;
3594 
3595     if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
3596     {
3597         context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
3598         return false;
3599     }
3600 
3601     // Check for invalid bits in the mask
3602     GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3603                                GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3604                                GL_MAP_UNSYNCHRONIZED_BIT;
3605 
3606     if (access & ~(allAccessBits))
3607     {
3608         context->handleError(InvalidValue()
3609                              << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
3610         return false;
3611     }
3612 
3613     if (length == 0)
3614     {
3615         context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
3616         return false;
3617     }
3618 
3619     if (buffer->isMapped())
3620     {
3621         context->handleError(InvalidOperation() << "Buffer is already mapped.");
3622         return false;
3623     }
3624 
3625     // Check for invalid bit combinations
3626     if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3627     {
3628         context->handleError(InvalidOperation()
3629                              << "Need to map buffer for either reading or writing.");
3630         return false;
3631     }
3632 
3633     GLbitfield writeOnlyBits =
3634         GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3635 
3636     if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3637     {
3638         context->handleError(InvalidOperation()
3639                              << "Invalid access bits when mapping buffer for reading: 0x"
3640                              << std::hex << std::uppercase << access);
3641         return false;
3642     }
3643 
3644     if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3645     {
3646         context->handleError(
3647             InvalidOperation()
3648             << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
3649         return false;
3650     }
3651 
3652     return ValidateMapBufferBase(context, target);
3653 }
3654 
ValidateFlushMappedBufferRangeBase(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)3655 bool ValidateFlushMappedBufferRangeBase(Context *context,
3656                                         BufferBinding target,
3657                                         GLintptr offset,
3658                                         GLsizeiptr length)
3659 {
3660     if (offset < 0)
3661     {
3662         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3663         return false;
3664     }
3665 
3666     if (length < 0)
3667     {
3668         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
3669         return false;
3670     }
3671 
3672     if (!ValidBufferType(context, target))
3673     {
3674         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
3675         return false;
3676     }
3677 
3678     Buffer *buffer = context->getGLState().getTargetBuffer(target);
3679 
3680     if (buffer == nullptr)
3681     {
3682         context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
3683         return false;
3684     }
3685 
3686     if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3687     {
3688         context->handleError(InvalidOperation()
3689                              << "Attempted to flush a buffer not mapped for explicit flushing.");
3690         return false;
3691     }
3692 
3693     // Check for buffer overflow
3694     CheckedNumeric<size_t> checkedOffset(offset);
3695     auto checkedSize = checkedOffset + length;
3696 
3697     if (!checkedSize.IsValid() ||
3698         checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
3699     {
3700         context->handleError(InvalidValue()
3701                              << "Flushed range does not fit into buffer mapping dimensions.");
3702         return false;
3703     }
3704 
3705     return true;
3706 }
3707 
ValidateGenOrDelete(Context * context,GLint n)3708 bool ValidateGenOrDelete(Context *context, GLint n)
3709 {
3710     if (n < 0)
3711     {
3712         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3713         return false;
3714     }
3715     return true;
3716 }
3717 
ValidateRobustEntryPoint(ValidationContext * context,GLsizei bufSize)3718 bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3719 {
3720     if (!context->getExtensions().robustClientMemory)
3721     {
3722         context->handleError(InvalidOperation()
3723                              << "GL_ANGLE_robust_client_memory is not available.");
3724         return false;
3725     }
3726 
3727     if (bufSize < 0)
3728     {
3729         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3730         return false;
3731     }
3732 
3733     return true;
3734 }
3735 
ValidateRobustBufferSize(ValidationContext * context,GLsizei bufSize,GLsizei numParams)3736 bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3737 {
3738     if (bufSize < numParams)
3739     {
3740         context->handleError(InvalidOperation() << numParams << " parameters are required but "
3741                                                 << bufSize << " were provided.");
3742         return false;
3743     }
3744 
3745     return true;
3746 }
3747 
ValidateGetFramebufferAttachmentParameterivBase(ValidationContext * context,GLenum target,GLenum attachment,GLenum pname,GLsizei * numParams)3748 bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3749                                                      GLenum target,
3750                                                      GLenum attachment,
3751                                                      GLenum pname,
3752                                                      GLsizei *numParams)
3753 {
3754     if (!ValidFramebufferTarget(context, target))
3755     {
3756         context->handleError(InvalidEnum());
3757         return false;
3758     }
3759 
3760     int clientVersion = context->getClientMajorVersion();
3761 
3762     switch (pname)
3763     {
3764         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3765         case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3766         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3767         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3768             break;
3769 
3770         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3771         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3772         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3773         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3774             if (clientVersion < 3 || !context->getExtensions().multiview)
3775             {
3776                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3777                 return false;
3778             }
3779             break;
3780 
3781         case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3782             if (clientVersion < 3 && !context->getExtensions().sRGB)
3783             {
3784                 context->handleError(InvalidEnum());
3785                 return false;
3786             }
3787             break;
3788 
3789         case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3790         case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3791         case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3792         case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3793         case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3794         case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3795         case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3796         case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3797             if (clientVersion < 3)
3798             {
3799                 context->handleError(InvalidEnum());
3800                 return false;
3801             }
3802             break;
3803 
3804         default:
3805             context->handleError(InvalidEnum());
3806             return false;
3807     }
3808 
3809     // Determine if the attachment is a valid enum
3810     switch (attachment)
3811     {
3812         case GL_BACK:
3813         case GL_DEPTH:
3814         case GL_STENCIL:
3815             if (clientVersion < 3)
3816             {
3817                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3818                 return false;
3819             }
3820             break;
3821 
3822         case GL_DEPTH_STENCIL_ATTACHMENT:
3823             if (clientVersion < 3 && !context->isWebGL1())
3824             {
3825                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3826                 return false;
3827             }
3828             break;
3829 
3830         case GL_COLOR_ATTACHMENT0:
3831         case GL_DEPTH_ATTACHMENT:
3832         case GL_STENCIL_ATTACHMENT:
3833             break;
3834 
3835         default:
3836             if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3837                 attachment < GL_COLOR_ATTACHMENT0_EXT ||
3838                 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3839             {
3840                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3841                 return false;
3842             }
3843             break;
3844     }
3845 
3846     const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3847     ASSERT(framebuffer);
3848 
3849     if (framebuffer->id() == 0)
3850     {
3851         if (clientVersion < 3)
3852         {
3853             ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
3854             return false;
3855         }
3856 
3857         switch (attachment)
3858         {
3859             case GL_BACK:
3860             case GL_DEPTH:
3861             case GL_STENCIL:
3862                 break;
3863 
3864             default:
3865                 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
3866                 return false;
3867         }
3868     }
3869     else
3870     {
3871         if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3872         {
3873             // Valid attachment query
3874         }
3875         else
3876         {
3877             switch (attachment)
3878             {
3879                 case GL_DEPTH_ATTACHMENT:
3880                 case GL_STENCIL_ATTACHMENT:
3881                     break;
3882 
3883                 case GL_DEPTH_STENCIL_ATTACHMENT:
3884                     if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
3885                     {
3886                         context->handleError(InvalidOperation());
3887                         return false;
3888                     }
3889                     break;
3890 
3891                 default:
3892                     ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
3893                     return false;
3894             }
3895         }
3896     }
3897 
3898     const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3899     if (attachmentObject)
3900     {
3901         ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3902                attachmentObject->type() == GL_TEXTURE ||
3903                attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3904 
3905         switch (pname)
3906         {
3907             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3908                 if (attachmentObject->type() != GL_RENDERBUFFER &&
3909                     attachmentObject->type() != GL_TEXTURE)
3910                 {
3911                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
3912                     return false;
3913                 }
3914                 break;
3915 
3916             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3917                 if (attachmentObject->type() != GL_TEXTURE)
3918                 {
3919                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
3920                     return false;
3921                 }
3922                 break;
3923 
3924             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3925                 if (attachmentObject->type() != GL_TEXTURE)
3926                 {
3927                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
3928                     return false;
3929                 }
3930                 break;
3931 
3932             case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3933                 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3934                 {
3935                     ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
3936                     return false;
3937                 }
3938                 break;
3939 
3940             case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3941                 if (attachmentObject->type() != GL_TEXTURE)
3942                 {
3943                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
3944                     return false;
3945                 }
3946                 break;
3947 
3948             default:
3949                 break;
3950         }
3951     }
3952     else
3953     {
3954         // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3955         // is NONE, then querying any other pname will generate INVALID_ENUM.
3956 
3957         // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3958         // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3959         // INVALID_OPERATION for all other pnames
3960 
3961         switch (pname)
3962         {
3963             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3964                 break;
3965 
3966             case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3967                 if (clientVersion < 3)
3968                 {
3969                     ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3970                                          InvalidFramebufferAttachmentParameter);
3971                     return false;
3972                 }
3973                 break;
3974 
3975             default:
3976                 if (clientVersion < 3)
3977                 {
3978                     ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3979                                          InvalidFramebufferAttachmentParameter);
3980                     return false;
3981                 }
3982                 else
3983                 {
3984                     ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3985                                          InvalidFramebufferAttachmentParameter);
3986                     return false;
3987                 }
3988         }
3989     }
3990 
3991     if (numParams)
3992     {
3993         if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3994         {
3995             // Only when the viewport offsets are queried we can have a varying number of output
3996             // parameters.
3997             const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3998             *numParams         = numViews * 2;
3999         }
4000         else
4001         {
4002             // For all other queries we can have only one output parameter.
4003             *numParams = 1;
4004         }
4005     }
4006 
4007     return true;
4008 }
4009 
ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext * context,GLenum target,GLenum attachment,GLenum pname,GLsizei bufSize,GLsizei * numParams)4010 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4011                                                             GLenum target,
4012                                                             GLenum attachment,
4013                                                             GLenum pname,
4014                                                             GLsizei bufSize,
4015                                                             GLsizei *numParams)
4016 {
4017     if (!ValidateRobustEntryPoint(context, bufSize))
4018     {
4019         return false;
4020     }
4021 
4022     if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4023                                                          numParams))
4024     {
4025         return false;
4026     }
4027 
4028     if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4029     {
4030         return false;
4031     }
4032 
4033     return true;
4034 }
4035 
ValidateGetBufferParameterivRobustANGLE(ValidationContext * context,BufferBinding target,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4036 bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4037                                              BufferBinding target,
4038                                              GLenum pname,
4039                                              GLsizei bufSize,
4040                                              GLsizei *length,
4041                                              GLint *params)
4042 {
4043     if (!ValidateRobustEntryPoint(context, bufSize))
4044     {
4045         return false;
4046     }
4047 
4048     if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4049     {
4050         return false;
4051     }
4052 
4053     if (!ValidateRobustBufferSize(context, bufSize, *length))
4054     {
4055         return false;
4056     }
4057 
4058     return true;
4059 }
4060 
ValidateGetBufferParameteri64vRobustANGLE(ValidationContext * context,BufferBinding target,GLenum pname,GLsizei bufSize,GLsizei * length,GLint64 * params)4061 bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4062                                                BufferBinding target,
4063                                                GLenum pname,
4064                                                GLsizei bufSize,
4065                                                GLsizei *length,
4066                                                GLint64 *params)
4067 {
4068     if (!ValidateRobustEntryPoint(context, bufSize))
4069     {
4070         return false;
4071     }
4072 
4073     if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4074     {
4075         return false;
4076     }
4077 
4078     if (!ValidateRobustBufferSize(context, bufSize, *length))
4079     {
4080         return false;
4081     }
4082 
4083     return true;
4084 }
4085 
ValidateGetProgramivBase(ValidationContext * context,GLuint program,GLenum pname,GLsizei * numParams)4086 bool ValidateGetProgramivBase(ValidationContext *context,
4087                               GLuint program,
4088                               GLenum pname,
4089                               GLsizei *numParams)
4090 {
4091     // Currently, all GetProgramiv queries return 1 parameter
4092     if (numParams)
4093     {
4094         *numParams = 1;
4095     }
4096 
4097     Program *programObject = GetValidProgram(context, program);
4098     if (!programObject)
4099     {
4100         return false;
4101     }
4102 
4103     switch (pname)
4104     {
4105         case GL_DELETE_STATUS:
4106         case GL_LINK_STATUS:
4107         case GL_VALIDATE_STATUS:
4108         case GL_INFO_LOG_LENGTH:
4109         case GL_ATTACHED_SHADERS:
4110         case GL_ACTIVE_ATTRIBUTES:
4111         case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4112         case GL_ACTIVE_UNIFORMS:
4113         case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4114             break;
4115 
4116         case GL_PROGRAM_BINARY_LENGTH:
4117             if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4118             {
4119                 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4120                                                       "requires GL_OES_get_program_binary or "
4121                                                       "ES 3.0.");
4122                 return false;
4123             }
4124             break;
4125 
4126         case GL_ACTIVE_UNIFORM_BLOCKS:
4127         case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4128         case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4129         case GL_TRANSFORM_FEEDBACK_VARYINGS:
4130         case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4131         case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4132             if (context->getClientMajorVersion() < 3)
4133             {
4134                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
4135                 return false;
4136             }
4137             break;
4138 
4139         case GL_PROGRAM_SEPARABLE:
4140         case GL_COMPUTE_WORK_GROUP_SIZE:
4141         case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
4142             if (context->getClientVersion() < Version(3, 1))
4143             {
4144                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4145                 return false;
4146             }
4147             break;
4148 
4149         default:
4150             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4151             return false;
4152     }
4153 
4154     return true;
4155 }
4156 
ValidateGetProgramivRobustANGLE(Context * context,GLuint program,GLenum pname,GLsizei bufSize,GLsizei * numParams)4157 bool ValidateGetProgramivRobustANGLE(Context *context,
4158                                      GLuint program,
4159                                      GLenum pname,
4160                                      GLsizei bufSize,
4161                                      GLsizei *numParams)
4162 {
4163     if (!ValidateRobustEntryPoint(context, bufSize))
4164     {
4165         return false;
4166     }
4167 
4168     if (!ValidateGetProgramivBase(context, program, pname, numParams))
4169     {
4170         return false;
4171     }
4172 
4173     if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4174     {
4175         return false;
4176     }
4177 
4178     return true;
4179 }
4180 
ValidateGetRenderbufferParameterivRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4181 bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4182                                                    GLenum target,
4183                                                    GLenum pname,
4184                                                    GLsizei bufSize,
4185                                                    GLsizei *length,
4186                                                    GLint *params)
4187 {
4188     if (!ValidateRobustEntryPoint(context, bufSize))
4189     {
4190         return false;
4191     }
4192 
4193     if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4194     {
4195         return false;
4196     }
4197 
4198     if (!ValidateRobustBufferSize(context, bufSize, *length))
4199     {
4200         return false;
4201     }
4202 
4203     return true;
4204 }
4205 
ValidateGetShaderivRobustANGLE(Context * context,GLuint shader,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4206 bool ValidateGetShaderivRobustANGLE(Context *context,
4207                                     GLuint shader,
4208                                     GLenum pname,
4209                                     GLsizei bufSize,
4210                                     GLsizei *length,
4211                                     GLint *params)
4212 {
4213     if (!ValidateRobustEntryPoint(context, bufSize))
4214     {
4215         return false;
4216     }
4217 
4218     if (!ValidateGetShaderivBase(context, shader, pname, length))
4219     {
4220         return false;
4221     }
4222 
4223     if (!ValidateRobustBufferSize(context, bufSize, *length))
4224     {
4225         return false;
4226     }
4227 
4228     return true;
4229 }
4230 
ValidateGetTexParameterfvRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,GLsizei * length,GLfloat * params)4231 bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4232                                           GLenum target,
4233                                           GLenum pname,
4234                                           GLsizei bufSize,
4235                                           GLsizei *length,
4236                                           GLfloat *params)
4237 {
4238     if (!ValidateRobustEntryPoint(context, bufSize))
4239     {
4240         return false;
4241     }
4242 
4243     if (!ValidateGetTexParameterBase(context, target, pname, length))
4244     {
4245         return false;
4246     }
4247 
4248     if (!ValidateRobustBufferSize(context, bufSize, *length))
4249     {
4250         return false;
4251     }
4252 
4253     return true;
4254 }
4255 
ValidateGetTexParameterivRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4256 bool ValidateGetTexParameterivRobustANGLE(Context *context,
4257                                           GLenum target,
4258                                           GLenum pname,
4259                                           GLsizei bufSize,
4260                                           GLsizei *length,
4261                                           GLint *params)
4262 {
4263     if (!ValidateRobustEntryPoint(context, bufSize))
4264     {
4265         return false;
4266     }
4267 
4268     if (!ValidateGetTexParameterBase(context, target, pname, length))
4269     {
4270         return false;
4271     }
4272 
4273     if (!ValidateRobustBufferSize(context, bufSize, *length))
4274     {
4275         return false;
4276     }
4277 
4278     return true;
4279 }
4280 
ValidateTexParameterfvRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,const GLfloat * params)4281 bool ValidateTexParameterfvRobustANGLE(Context *context,
4282                                        GLenum target,
4283                                        GLenum pname,
4284                                        GLsizei bufSize,
4285                                        const GLfloat *params)
4286 {
4287     if (!ValidateRobustEntryPoint(context, bufSize))
4288     {
4289         return false;
4290     }
4291 
4292     return ValidateTexParameterBase(context, target, pname, bufSize, params);
4293 }
4294 
ValidateTexParameterivRobustANGLE(Context * context,GLenum target,GLenum pname,GLsizei bufSize,const GLint * params)4295 bool ValidateTexParameterivRobustANGLE(Context *context,
4296                                        GLenum target,
4297                                        GLenum pname,
4298                                        GLsizei bufSize,
4299                                        const GLint *params)
4300 {
4301     if (!ValidateRobustEntryPoint(context, bufSize))
4302     {
4303         return false;
4304     }
4305 
4306     return ValidateTexParameterBase(context, target, pname, bufSize, params);
4307 }
4308 
ValidateGetSamplerParameterfvRobustANGLE(Context * context,GLuint sampler,GLenum pname,GLuint bufSize,GLsizei * length,GLfloat * params)4309 bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4310                                               GLuint sampler,
4311                                               GLenum pname,
4312                                               GLuint bufSize,
4313                                               GLsizei *length,
4314                                               GLfloat *params)
4315 {
4316     if (!ValidateRobustEntryPoint(context, bufSize))
4317     {
4318         return false;
4319     }
4320 
4321     if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4322     {
4323         return false;
4324     }
4325 
4326     if (!ValidateRobustBufferSize(context, bufSize, *length))
4327     {
4328         return false;
4329     }
4330 
4331     return true;
4332 }
4333 
ValidateGetSamplerParameterivRobustANGLE(Context * context,GLuint sampler,GLenum pname,GLuint bufSize,GLsizei * length,GLint * params)4334 bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4335                                               GLuint sampler,
4336                                               GLenum pname,
4337                                               GLuint bufSize,
4338                                               GLsizei *length,
4339                                               GLint *params)
4340 {
4341     if (!ValidateRobustEntryPoint(context, bufSize))
4342     {
4343         return false;
4344     }
4345 
4346     if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4347     {
4348         return false;
4349     }
4350 
4351     if (!ValidateRobustBufferSize(context, bufSize, *length))
4352     {
4353         return false;
4354     }
4355 
4356     return true;
4357 }
4358 
ValidateSamplerParameterfvRobustANGLE(Context * context,GLuint sampler,GLenum pname,GLsizei bufSize,const GLfloat * params)4359 bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4360                                            GLuint sampler,
4361                                            GLenum pname,
4362                                            GLsizei bufSize,
4363                                            const GLfloat *params)
4364 {
4365     if (!ValidateRobustEntryPoint(context, bufSize))
4366     {
4367         return false;
4368     }
4369 
4370     return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4371 }
4372 
ValidateSamplerParameterivRobustANGLE(Context * context,GLuint sampler,GLenum pname,GLsizei bufSize,const GLint * params)4373 bool ValidateSamplerParameterivRobustANGLE(Context *context,
4374                                            GLuint sampler,
4375                                            GLenum pname,
4376                                            GLsizei bufSize,
4377                                            const GLint *params)
4378 {
4379     if (!ValidateRobustEntryPoint(context, bufSize))
4380     {
4381         return false;
4382     }
4383 
4384     return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4385 }
4386 
ValidateGetVertexAttribfvRobustANGLE(Context * context,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,GLfloat * params)4387 bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4388                                           GLuint index,
4389                                           GLenum pname,
4390                                           GLsizei bufSize,
4391                                           GLsizei *length,
4392                                           GLfloat *params)
4393 {
4394     if (!ValidateRobustEntryPoint(context, bufSize))
4395     {
4396         return false;
4397     }
4398 
4399     if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4400     {
4401         return false;
4402     }
4403 
4404     if (!ValidateRobustBufferSize(context, bufSize, *length))
4405     {
4406         return false;
4407     }
4408 
4409     return true;
4410 }
4411 
ValidateGetVertexAttribivRobustANGLE(Context * context,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4412 bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4413                                           GLuint index,
4414                                           GLenum pname,
4415                                           GLsizei bufSize,
4416                                           GLsizei *length,
4417                                           GLint *params)
4418 {
4419     if (!ValidateRobustEntryPoint(context, bufSize))
4420     {
4421         return false;
4422     }
4423 
4424     if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4425     {
4426         return false;
4427     }
4428 
4429     if (!ValidateRobustBufferSize(context, bufSize, *length))
4430     {
4431         return false;
4432     }
4433 
4434     return true;
4435 }
4436 
ValidateGetVertexAttribPointervRobustANGLE(Context * context,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,void ** pointer)4437 bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4438                                                 GLuint index,
4439                                                 GLenum pname,
4440                                                 GLsizei bufSize,
4441                                                 GLsizei *length,
4442                                                 void **pointer)
4443 {
4444     if (!ValidateRobustEntryPoint(context, bufSize))
4445     {
4446         return false;
4447     }
4448 
4449     if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4450     {
4451         return false;
4452     }
4453 
4454     if (!ValidateRobustBufferSize(context, bufSize, *length))
4455     {
4456         return false;
4457     }
4458 
4459     return true;
4460 }
4461 
ValidateGetVertexAttribIivRobustANGLE(Context * context,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4462 bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4463                                            GLuint index,
4464                                            GLenum pname,
4465                                            GLsizei bufSize,
4466                                            GLsizei *length,
4467                                            GLint *params)
4468 {
4469     if (!ValidateRobustEntryPoint(context, bufSize))
4470     {
4471         return false;
4472     }
4473 
4474     if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4475     {
4476         return false;
4477     }
4478 
4479     if (!ValidateRobustBufferSize(context, bufSize, *length))
4480     {
4481         return false;
4482     }
4483 
4484     return true;
4485 }
4486 
ValidateGetVertexAttribIuivRobustANGLE(Context * context,GLuint index,GLenum pname,GLsizei bufSize,GLsizei * length,GLuint * params)4487 bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4488                                             GLuint index,
4489                                             GLenum pname,
4490                                             GLsizei bufSize,
4491                                             GLsizei *length,
4492                                             GLuint *params)
4493 {
4494     if (!ValidateRobustEntryPoint(context, bufSize))
4495     {
4496         return false;
4497     }
4498 
4499     if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4500     {
4501         return false;
4502     }
4503 
4504     if (!ValidateRobustBufferSize(context, bufSize, *length))
4505     {
4506         return false;
4507     }
4508 
4509     return true;
4510 }
4511 
ValidateGetActiveUniformBlockivRobustANGLE(Context * context,GLuint program,GLuint uniformBlockIndex,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4512 bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4513                                                 GLuint program,
4514                                                 GLuint uniformBlockIndex,
4515                                                 GLenum pname,
4516                                                 GLsizei bufSize,
4517                                                 GLsizei *length,
4518                                                 GLint *params)
4519 {
4520     if (!ValidateRobustEntryPoint(context, bufSize))
4521     {
4522         return false;
4523     }
4524 
4525     if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4526     {
4527         return false;
4528     }
4529 
4530     if (!ValidateRobustBufferSize(context, bufSize, *length))
4531     {
4532         return false;
4533     }
4534 
4535     return true;
4536 }
4537 
ValidateGetInternalFormativRobustANGLE(Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * params)4538 bool ValidateGetInternalFormativRobustANGLE(Context *context,
4539                                             GLenum target,
4540                                             GLenum internalformat,
4541                                             GLenum pname,
4542                                             GLsizei bufSize,
4543                                             GLsizei *length,
4544                                             GLint *params)
4545 {
4546     if (!ValidateRobustEntryPoint(context, bufSize))
4547     {
4548         return false;
4549     }
4550 
4551     if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4552     {
4553         return false;
4554     }
4555 
4556     if (!ValidateRobustBufferSize(context, bufSize, *length))
4557     {
4558         return false;
4559     }
4560 
4561     return true;
4562 }
4563 
ValidateVertexFormatBase(ValidationContext * context,GLuint attribIndex,GLint size,GLenum type,GLboolean pureInteger)4564 bool ValidateVertexFormatBase(ValidationContext *context,
4565                               GLuint attribIndex,
4566                               GLint size,
4567                               GLenum type,
4568                               GLboolean pureInteger)
4569 {
4570     const Caps &caps = context->getCaps();
4571     if (attribIndex >= caps.maxVertexAttributes)
4572     {
4573         ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
4574         return false;
4575     }
4576 
4577     if (size < 1 || size > 4)
4578     {
4579         ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
4580         return false;
4581     }
4582 
4583     switch (type)
4584     {
4585         case GL_BYTE:
4586         case GL_UNSIGNED_BYTE:
4587         case GL_SHORT:
4588         case GL_UNSIGNED_SHORT:
4589             break;
4590 
4591         case GL_INT:
4592         case GL_UNSIGNED_INT:
4593             if (context->getClientMajorVersion() < 3)
4594             {
4595                 context->handleError(InvalidEnum()
4596                                      << "Vertex type not supported before OpenGL ES 3.0.");
4597                 return false;
4598             }
4599             break;
4600 
4601         case GL_FIXED:
4602         case GL_FLOAT:
4603             if (pureInteger)
4604             {
4605                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
4606                 return false;
4607             }
4608             break;
4609 
4610         case GL_HALF_FLOAT:
4611             if (context->getClientMajorVersion() < 3)
4612             {
4613                 context->handleError(InvalidEnum()
4614                                      << "Vertex type not supported before OpenGL ES 3.0.");
4615                 return false;
4616             }
4617             if (pureInteger)
4618             {
4619                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
4620                 return false;
4621             }
4622             break;
4623 
4624         case GL_INT_2_10_10_10_REV:
4625         case GL_UNSIGNED_INT_2_10_10_10_REV:
4626             if (context->getClientMajorVersion() < 3)
4627             {
4628                 context->handleError(InvalidEnum()
4629                                      << "Vertex type not supported before OpenGL ES 3.0.");
4630                 return false;
4631             }
4632             if (pureInteger)
4633             {
4634                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
4635                 return false;
4636             }
4637             if (size != 4)
4638             {
4639                 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4640                                                            "UNSIGNED_INT_2_10_10_10_REV and "
4641                                                            "size is not 4.");
4642                 return false;
4643             }
4644             break;
4645 
4646         default:
4647             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
4648             return false;
4649     }
4650 
4651     return true;
4652 }
4653 
4654 // Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4655 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4656 // specified clear value and the type of a buffer that is being cleared generates an
4657 // INVALID_OPERATION error instead of producing undefined results
ValidateWebGLFramebufferAttachmentClearType(ValidationContext * context,GLint drawbuffer,const GLenum * validComponentTypes,size_t validComponentTypeCount)4658 bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4659                                                  GLint drawbuffer,
4660                                                  const GLenum *validComponentTypes,
4661                                                  size_t validComponentTypeCount)
4662 {
4663     const FramebufferAttachment *attachment =
4664         context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4665     if (attachment)
4666     {
4667         GLenum componentType = attachment->getFormat().info->componentType;
4668         const GLenum *end    = validComponentTypes + validComponentTypeCount;
4669         if (std::find(validComponentTypes, end, componentType) == end)
4670         {
4671             context->handleError(
4672                 InvalidOperation()
4673                 << "No defined conversion between clear value and attachment format.");
4674             return false;
4675         }
4676     }
4677 
4678     return true;
4679 }
4680 
ValidateRobustCompressedTexImageBase(ValidationContext * context,GLsizei imageSize,GLsizei dataSize)4681 bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4682                                           GLsizei imageSize,
4683                                           GLsizei dataSize)
4684 {
4685     if (!ValidateRobustEntryPoint(context, dataSize))
4686     {
4687         return false;
4688     }
4689 
4690     gl::Buffer *pixelUnpackBuffer =
4691         context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
4692     if (pixelUnpackBuffer == nullptr)
4693     {
4694         if (dataSize < imageSize)
4695         {
4696             context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
4697         }
4698     }
4699     return true;
4700 }
4701 
ValidateGetBufferParameterBase(ValidationContext * context,BufferBinding target,GLenum pname,bool pointerVersion,GLsizei * numParams)4702 bool ValidateGetBufferParameterBase(ValidationContext *context,
4703                                     BufferBinding target,
4704                                     GLenum pname,
4705                                     bool pointerVersion,
4706                                     GLsizei *numParams)
4707 {
4708     if (numParams)
4709     {
4710         *numParams = 0;
4711     }
4712 
4713     if (!ValidBufferType(context, target))
4714     {
4715         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
4716         return false;
4717     }
4718 
4719     const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4720     if (!buffer)
4721     {
4722         // A null buffer means that "0" is bound to the requested buffer target
4723         ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
4724         return false;
4725     }
4726 
4727     const Extensions &extensions = context->getExtensions();
4728 
4729     switch (pname)
4730     {
4731         case GL_BUFFER_USAGE:
4732         case GL_BUFFER_SIZE:
4733             break;
4734 
4735         case GL_BUFFER_ACCESS_OES:
4736             if (!extensions.mapBuffer)
4737             {
4738                 context->handleError(InvalidEnum()
4739                                      << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
4740                 return false;
4741             }
4742             break;
4743 
4744         case GL_BUFFER_MAPPED:
4745             static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4746             if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4747                 !extensions.mapBufferRange)
4748             {
4749                 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4750                                                       "GL_OES_mapbuffer or "
4751                                                       "GL_EXT_map_buffer_range.");
4752                 return false;
4753             }
4754             break;
4755 
4756         case GL_BUFFER_MAP_POINTER:
4757             if (!pointerVersion)
4758             {
4759                 context->handleError(
4760                     InvalidEnum()
4761                     << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
4762                 return false;
4763             }
4764             break;
4765 
4766         case GL_BUFFER_ACCESS_FLAGS:
4767         case GL_BUFFER_MAP_OFFSET:
4768         case GL_BUFFER_MAP_LENGTH:
4769             if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4770             {
4771                 context->handleError(InvalidEnum()
4772                                      << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
4773                 return false;
4774             }
4775             break;
4776 
4777         default:
4778             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4779             return false;
4780     }
4781 
4782     // All buffer parameter queries return one value.
4783     if (numParams)
4784     {
4785         *numParams = 1;
4786     }
4787 
4788     return true;
4789 }
4790 
ValidateGetRenderbufferParameterivBase(Context * context,GLenum target,GLenum pname,GLsizei * length)4791 bool ValidateGetRenderbufferParameterivBase(Context *context,
4792                                             GLenum target,
4793                                             GLenum pname,
4794                                             GLsizei *length)
4795 {
4796     if (length)
4797     {
4798         *length = 0;
4799     }
4800 
4801     if (target != GL_RENDERBUFFER)
4802     {
4803         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
4804         return false;
4805     }
4806 
4807     Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4808     if (renderbuffer == nullptr)
4809     {
4810         ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
4811         return false;
4812     }
4813 
4814     switch (pname)
4815     {
4816         case GL_RENDERBUFFER_WIDTH:
4817         case GL_RENDERBUFFER_HEIGHT:
4818         case GL_RENDERBUFFER_INTERNAL_FORMAT:
4819         case GL_RENDERBUFFER_RED_SIZE:
4820         case GL_RENDERBUFFER_GREEN_SIZE:
4821         case GL_RENDERBUFFER_BLUE_SIZE:
4822         case GL_RENDERBUFFER_ALPHA_SIZE:
4823         case GL_RENDERBUFFER_DEPTH_SIZE:
4824         case GL_RENDERBUFFER_STENCIL_SIZE:
4825             break;
4826 
4827         case GL_RENDERBUFFER_SAMPLES_ANGLE:
4828             if (!context->getExtensions().framebufferMultisample)
4829             {
4830                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
4831                 return false;
4832             }
4833             break;
4834 
4835         default:
4836             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4837             return false;
4838     }
4839 
4840     if (length)
4841     {
4842         *length = 1;
4843     }
4844     return true;
4845 }
4846 
ValidateGetShaderivBase(Context * context,GLuint shader,GLenum pname,GLsizei * length)4847 bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4848 {
4849     if (length)
4850     {
4851         *length = 0;
4852     }
4853 
4854     if (GetValidShader(context, shader) == nullptr)
4855     {
4856         return false;
4857     }
4858 
4859     switch (pname)
4860     {
4861         case GL_SHADER_TYPE:
4862         case GL_DELETE_STATUS:
4863         case GL_COMPILE_STATUS:
4864         case GL_INFO_LOG_LENGTH:
4865         case GL_SHADER_SOURCE_LENGTH:
4866             break;
4867 
4868         case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4869             if (!context->getExtensions().translatedShaderSource)
4870             {
4871                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
4872                 return false;
4873             }
4874             break;
4875 
4876         default:
4877             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4878             return false;
4879     }
4880 
4881     if (length)
4882     {
4883         *length = 1;
4884     }
4885     return true;
4886 }
4887 
ValidateGetTexParameterBase(Context * context,GLenum target,GLenum pname,GLsizei * length)4888 bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4889 {
4890     if (length)
4891     {
4892         *length = 0;
4893     }
4894 
4895     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4896     {
4897         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
4898         return false;
4899     }
4900 
4901     if (context->getTargetTexture(target) == nullptr)
4902     {
4903         // Should only be possible for external textures
4904         ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
4905         return false;
4906     }
4907 
4908     switch (pname)
4909     {
4910         case GL_TEXTURE_MAG_FILTER:
4911         case GL_TEXTURE_MIN_FILTER:
4912         case GL_TEXTURE_WRAP_S:
4913         case GL_TEXTURE_WRAP_T:
4914             break;
4915 
4916         case GL_TEXTURE_USAGE_ANGLE:
4917             if (!context->getExtensions().textureUsage)
4918             {
4919                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
4920                 return false;
4921             }
4922             break;
4923 
4924         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4925             if (!context->getExtensions().textureFilterAnisotropic)
4926             {
4927                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
4928                 return false;
4929             }
4930             break;
4931 
4932         case GL_TEXTURE_IMMUTABLE_FORMAT:
4933             if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4934             {
4935                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
4936                 return false;
4937             }
4938             break;
4939 
4940         case GL_TEXTURE_WRAP_R:
4941         case GL_TEXTURE_IMMUTABLE_LEVELS:
4942         case GL_TEXTURE_SWIZZLE_R:
4943         case GL_TEXTURE_SWIZZLE_G:
4944         case GL_TEXTURE_SWIZZLE_B:
4945         case GL_TEXTURE_SWIZZLE_A:
4946         case GL_TEXTURE_BASE_LEVEL:
4947         case GL_TEXTURE_MAX_LEVEL:
4948         case GL_TEXTURE_MIN_LOD:
4949         case GL_TEXTURE_MAX_LOD:
4950         case GL_TEXTURE_COMPARE_MODE:
4951         case GL_TEXTURE_COMPARE_FUNC:
4952             if (context->getClientMajorVersion() < 3)
4953             {
4954                 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
4955                 return false;
4956             }
4957             break;
4958 
4959         case GL_TEXTURE_SRGB_DECODE_EXT:
4960             if (!context->getExtensions().textureSRGBDecode)
4961             {
4962                 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
4963                 return false;
4964             }
4965             break;
4966 
4967         default:
4968             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4969             return false;
4970     }
4971 
4972     if (length)
4973     {
4974         *length = 1;
4975     }
4976     return true;
4977 }
4978 
ValidateGetVertexAttribBase(Context * context,GLuint index,GLenum pname,GLsizei * length,bool pointer,bool pureIntegerEntryPoint)4979 bool ValidateGetVertexAttribBase(Context *context,
4980                                  GLuint index,
4981                                  GLenum pname,
4982                                  GLsizei *length,
4983                                  bool pointer,
4984                                  bool pureIntegerEntryPoint)
4985 {
4986     if (length)
4987     {
4988         *length = 0;
4989     }
4990 
4991     if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4992     {
4993         context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
4994         return false;
4995     }
4996 
4997     if (index >= context->getCaps().maxVertexAttributes)
4998     {
4999         ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5000         return false;
5001     }
5002 
5003     if (pointer)
5004     {
5005         if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5006         {
5007             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5008             return false;
5009         }
5010     }
5011     else
5012     {
5013         switch (pname)
5014         {
5015             case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5016             case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5017             case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5018             case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5019             case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5020             case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5021             case GL_CURRENT_VERTEX_ATTRIB:
5022                 break;
5023 
5024             case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5025                 static_assert(
5026                     GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5027                     "ANGLE extension enums not equal to GL enums.");
5028                 if (context->getClientMajorVersion() < 3 &&
5029                     !context->getExtensions().instancedArrays)
5030                 {
5031                     context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5032                                                           "requires OpenGL ES 3.0 or "
5033                                                           "GL_ANGLE_instanced_arrays.");
5034                     return false;
5035                 }
5036                 break;
5037 
5038             case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5039                 if (context->getClientMajorVersion() < 3)
5040                 {
5041                     context->handleError(
5042                         InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
5043                     return false;
5044                 }
5045                 break;
5046 
5047             case GL_VERTEX_ATTRIB_BINDING:
5048             case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5049                 if (context->getClientVersion() < ES_3_1)
5050                 {
5051                     context->handleError(InvalidEnum()
5052                                          << "Vertex Attrib Bindings require OpenGL ES 3.1.");
5053                     return false;
5054                 }
5055                 break;
5056 
5057             default:
5058                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5059                 return false;
5060         }
5061     }
5062 
5063     if (length)
5064     {
5065         if (pname == GL_CURRENT_VERTEX_ATTRIB)
5066         {
5067             *length = 4;
5068         }
5069         else
5070         {
5071             *length = 1;
5072         }
5073     }
5074 
5075     return true;
5076 }
5077 
ValidateReadPixelsBase(Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,void * pixels)5078 bool ValidateReadPixelsBase(Context *context,
5079                             GLint x,
5080                             GLint y,
5081                             GLsizei width,
5082                             GLsizei height,
5083                             GLenum format,
5084                             GLenum type,
5085                             GLsizei bufSize,
5086                             GLsizei *length,
5087                             GLsizei *columns,
5088                             GLsizei *rows,
5089                             void *pixels)
5090 {
5091     if (length != nullptr)
5092     {
5093         *length = 0;
5094     }
5095     if (rows != nullptr)
5096     {
5097         *rows = 0;
5098     }
5099     if (columns != nullptr)
5100     {
5101         *columns = 0;
5102     }
5103 
5104     if (width < 0 || height < 0)
5105     {
5106         ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
5107         return false;
5108     }
5109 
5110     Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
5111 
5112     if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5113     {
5114         context->handleError(InvalidFramebufferOperation());
5115         return false;
5116     }
5117 
5118     if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5119     {
5120         context->handleError(InvalidOperation());
5121         return false;
5122     }
5123 
5124     const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5125     ASSERT(framebuffer);
5126 
5127     if (framebuffer->getReadBufferState() == GL_NONE)
5128     {
5129         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
5130         return false;
5131     }
5132 
5133     const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5134     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5135     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5136     // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5137     // situation is an application error that would lead to a crash in ANGLE.
5138     if (readBuffer == nullptr)
5139     {
5140         ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
5141         return false;
5142     }
5143 
5144     // ANGLE_multiview, Revision 1:
5145     // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5146     // current read framebuffer is not NONE.
5147     if (readBuffer->getMultiviewLayout() != GL_NONE)
5148     {
5149         context->handleError(InvalidFramebufferOperation()
5150                              << "Attempting to read from a multi-view framebuffer.");
5151         return false;
5152     }
5153 
5154     if (context->getExtensions().webglCompatibility)
5155     {
5156         // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5157         // excluding formats LUMINANCE and LUMINANCE_ALPHA.".  This requires validating the format
5158         // and type before validating the combination of format and type.  However, the
5159         // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5160         // verifies that GL_INVALID_OPERATION is generated.
5161         // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5162         // dEQP/WebGL.
5163         if (!ValidReadPixelsFormatEnum(context, format))
5164         {
5165             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
5166             return false;
5167         }
5168 
5169         if (!ValidReadPixelsTypeEnum(context, type))
5170         {
5171             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
5172             return false;
5173         }
5174     }
5175 
5176     GLenum currentFormat        = framebuffer->getImplementationColorReadFormat(context);
5177     GLenum currentType          = framebuffer->getImplementationColorReadType(context);
5178     GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5179 
5180     bool validFormatTypeCombination =
5181         ValidReadPixelsFormatType(context, currentComponentType, format, type);
5182 
5183     if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5184     {
5185         ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
5186         return false;
5187     }
5188 
5189     // Check for pixel pack buffer related API errors
5190     gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
5191     if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5192     {
5193         // ...the buffer object's data store is currently mapped.
5194         context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
5195         return false;
5196     }
5197 
5198     // ..  the data would be packed to the buffer object such that the memory writes required
5199     // would exceed the data store size.
5200     const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5201     const gl::Extents size(width, height, 1);
5202     const auto &pack = context->getGLState().getPackState();
5203 
5204     auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5205     if (endByteOrErr.isError())
5206     {
5207         context->handleError(endByteOrErr.getError());
5208         return false;
5209     }
5210 
5211     size_t endByte = endByteOrErr.getResult();
5212     if (bufSize >= 0)
5213     {
5214         if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5215         {
5216             ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5217             return false;
5218         }
5219     }
5220 
5221     if (pixelPackBuffer != nullptr)
5222     {
5223         CheckedNumeric<size_t> checkedEndByte(endByte);
5224         CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5225         checkedEndByte += checkedOffset;
5226 
5227         if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5228         {
5229             // Overflow past the end of the buffer
5230             ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
5231             return false;
5232         }
5233     }
5234 
5235     if (pixelPackBuffer == nullptr && length != nullptr)
5236     {
5237         if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5238         {
5239             ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5240             return false;
5241         }
5242 
5243         *length = static_cast<GLsizei>(endByte);
5244     }
5245 
5246     auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5247         angle::CheckedNumeric<int> clippedExtent(length);
5248         if (start < 0)
5249         {
5250             // "subtract" the area that is less than 0
5251             clippedExtent += start;
5252         }
5253 
5254         const int readExtent = start + length;
5255         if (readExtent > bufferSize)
5256         {
5257             // Subtract the region to the right of the read buffer
5258             clippedExtent -= (readExtent - bufferSize);
5259         }
5260 
5261         if (!clippedExtent.IsValid())
5262         {
5263             return 0;
5264         }
5265 
5266         return std::max(clippedExtent.ValueOrDie(), 0);
5267     };
5268 
5269     if (columns != nullptr)
5270     {
5271         *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5272     }
5273 
5274     if (rows != nullptr)
5275     {
5276         *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5277     }
5278 
5279     return true;
5280 }
5281 
5282 template <typename ParamType>
ValidateTexParameterBase(Context * context,GLenum target,GLenum pname,GLsizei bufSize,const ParamType * params)5283 bool ValidateTexParameterBase(Context *context,
5284                               GLenum target,
5285                               GLenum pname,
5286                               GLsizei bufSize,
5287                               const ParamType *params)
5288 {
5289     if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5290     {
5291         ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
5292         return false;
5293     }
5294 
5295     if (context->getTargetTexture(target) == nullptr)
5296     {
5297         // Should only be possible for external textures
5298         ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
5299         return false;
5300     }
5301 
5302     const GLsizei minBufSize = 1;
5303     if (bufSize >= 0 && bufSize < minBufSize)
5304     {
5305         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5306         return false;
5307     }
5308 
5309     switch (pname)
5310     {
5311         case GL_TEXTURE_WRAP_R:
5312         case GL_TEXTURE_SWIZZLE_R:
5313         case GL_TEXTURE_SWIZZLE_G:
5314         case GL_TEXTURE_SWIZZLE_B:
5315         case GL_TEXTURE_SWIZZLE_A:
5316         case GL_TEXTURE_BASE_LEVEL:
5317         case GL_TEXTURE_MAX_LEVEL:
5318         case GL_TEXTURE_COMPARE_MODE:
5319         case GL_TEXTURE_COMPARE_FUNC:
5320         case GL_TEXTURE_MIN_LOD:
5321         case GL_TEXTURE_MAX_LOD:
5322             if (context->getClientMajorVersion() < 3)
5323             {
5324                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
5325                 return false;
5326             }
5327             if (target == GL_TEXTURE_EXTERNAL_OES &&
5328                 !context->getExtensions().eglImageExternalEssl3)
5329             {
5330                 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5331                                                       "available without "
5332                                                       "GL_OES_EGL_image_external_essl3.");
5333                 return false;
5334             }
5335             break;
5336 
5337         default:
5338             break;
5339     }
5340 
5341     if (target == GL_TEXTURE_2D_MULTISAMPLE)
5342     {
5343         switch (pname)
5344         {
5345             case GL_TEXTURE_MIN_FILTER:
5346             case GL_TEXTURE_MAG_FILTER:
5347             case GL_TEXTURE_WRAP_S:
5348             case GL_TEXTURE_WRAP_T:
5349             case GL_TEXTURE_WRAP_R:
5350             case GL_TEXTURE_MIN_LOD:
5351             case GL_TEXTURE_MAX_LOD:
5352             case GL_TEXTURE_COMPARE_MODE:
5353             case GL_TEXTURE_COMPARE_FUNC:
5354                 context->handleError(InvalidEnum()
5355                                      << "Invalid parameter for 2D multisampled textures.");
5356                 return false;
5357         }
5358     }
5359 
5360     switch (pname)
5361     {
5362         case GL_TEXTURE_WRAP_S:
5363         case GL_TEXTURE_WRAP_T:
5364         case GL_TEXTURE_WRAP_R:
5365             {
5366                 bool restrictedWrapModes =
5367                     target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5368                 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5369                 {
5370                     return false;
5371                 }
5372             }
5373             break;
5374 
5375         case GL_TEXTURE_MIN_FILTER:
5376             {
5377                 bool restrictedMinFilter =
5378                     target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5379                 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5380                 {
5381                     return false;
5382                 }
5383             }
5384             break;
5385 
5386         case GL_TEXTURE_MAG_FILTER:
5387             if (!ValidateTextureMagFilterValue(context, params))
5388             {
5389                 return false;
5390             }
5391             break;
5392 
5393         case GL_TEXTURE_USAGE_ANGLE:
5394             if (!context->getExtensions().textureUsage)
5395             {
5396                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5397                 return false;
5398             }
5399 
5400             switch (ConvertToGLenum(params[0]))
5401             {
5402                 case GL_NONE:
5403                 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5404                     break;
5405 
5406                 default:
5407                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5408                     return false;
5409             }
5410             break;
5411 
5412         case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5413             if (!context->getExtensions().textureFilterAnisotropic)
5414             {
5415                 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
5416                 return false;
5417             }
5418 
5419             // we assume the parameter passed to this validation method is truncated, not rounded
5420             if (params[0] < 1)
5421             {
5422                 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
5423                 return false;
5424             }
5425             break;
5426 
5427         case GL_TEXTURE_MIN_LOD:
5428         case GL_TEXTURE_MAX_LOD:
5429             // any value is permissible
5430             break;
5431 
5432         case GL_TEXTURE_COMPARE_MODE:
5433             if (!ValidateTextureCompareModeValue(context, params))
5434             {
5435                 return false;
5436             }
5437             break;
5438 
5439         case GL_TEXTURE_COMPARE_FUNC:
5440             if (!ValidateTextureCompareFuncValue(context, params))
5441             {
5442                 return false;
5443             }
5444             break;
5445 
5446         case GL_TEXTURE_SWIZZLE_R:
5447         case GL_TEXTURE_SWIZZLE_G:
5448         case GL_TEXTURE_SWIZZLE_B:
5449         case GL_TEXTURE_SWIZZLE_A:
5450             switch (ConvertToGLenum(params[0]))
5451             {
5452                 case GL_RED:
5453                 case GL_GREEN:
5454                 case GL_BLUE:
5455                 case GL_ALPHA:
5456                 case GL_ZERO:
5457                 case GL_ONE:
5458                     break;
5459 
5460                 default:
5461                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5462                     return false;
5463             }
5464             break;
5465 
5466         case GL_TEXTURE_BASE_LEVEL:
5467             if (ConvertToGLint(params[0]) < 0)
5468             {
5469                 context->handleError(InvalidValue() << "Base level must be at least 0.");
5470                 return false;
5471             }
5472             if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5473             {
5474                 context->handleError(InvalidOperation()
5475                                      << "Base level must be 0 for external textures.");
5476                 return false;
5477             }
5478             if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5479             {
5480                 context->handleError(InvalidOperation()
5481                                      << "Base level must be 0 for multisampled textures.");
5482                 return false;
5483             }
5484             if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5485             {
5486                 context->handleError(InvalidOperation()
5487                                      << "Base level must be 0 for rectangle textures.");
5488                 return false;
5489             }
5490             break;
5491 
5492         case GL_TEXTURE_MAX_LEVEL:
5493             if (ConvertToGLint(params[0]) < 0)
5494             {
5495                 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
5496                 return false;
5497             }
5498             break;
5499 
5500         case GL_DEPTH_STENCIL_TEXTURE_MODE:
5501             if (context->getClientVersion() < Version(3, 1))
5502             {
5503                 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5504                 return false;
5505             }
5506             switch (ConvertToGLenum(params[0]))
5507             {
5508                 case GL_DEPTH_COMPONENT:
5509                 case GL_STENCIL_INDEX:
5510                     break;
5511 
5512                 default:
5513                     ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5514                     return false;
5515             }
5516             break;
5517 
5518         case GL_TEXTURE_SRGB_DECODE_EXT:
5519             if (!ValidateTextureSRGBDecodeValue(context, params))
5520             {
5521                 return false;
5522             }
5523             break;
5524 
5525         default:
5526             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5527             return false;
5528     }
5529 
5530     return true;
5531 }
5532 
5533 template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5534 template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5535 
ValidateVertexAttribIndex(ValidationContext * context,GLuint index)5536 bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5537 {
5538     if (index >= MAX_VERTEX_ATTRIBS)
5539     {
5540         ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5541         return false;
5542     }
5543 
5544     return true;
5545 }
5546 
ValidateGetActiveUniformBlockivBase(Context * context,GLuint program,GLuint uniformBlockIndex,GLenum pname,GLsizei * length)5547 bool ValidateGetActiveUniformBlockivBase(Context *context,
5548                                          GLuint program,
5549                                          GLuint uniformBlockIndex,
5550                                          GLenum pname,
5551                                          GLsizei *length)
5552 {
5553     if (length)
5554     {
5555         *length = 0;
5556     }
5557 
5558     if (context->getClientMajorVersion() < 3)
5559     {
5560         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5561         return false;
5562     }
5563 
5564     Program *programObject = GetValidProgram(context, program);
5565     if (!programObject)
5566     {
5567         return false;
5568     }
5569 
5570     if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5571     {
5572         context->handleError(InvalidValue()
5573                              << "uniformBlockIndex exceeds active uniform block count.");
5574         return false;
5575     }
5576 
5577     switch (pname)
5578     {
5579         case GL_UNIFORM_BLOCK_BINDING:
5580         case GL_UNIFORM_BLOCK_DATA_SIZE:
5581         case GL_UNIFORM_BLOCK_NAME_LENGTH:
5582         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5583         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5584         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5585         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5586             break;
5587 
5588         default:
5589             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5590             return false;
5591     }
5592 
5593     if (length)
5594     {
5595         if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5596         {
5597             const InterfaceBlock &uniformBlock =
5598                 programObject->getUniformBlockByIndex(uniformBlockIndex);
5599             *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5600         }
5601         else
5602         {
5603             *length = 1;
5604         }
5605     }
5606 
5607     return true;
5608 }
5609 
5610 template <typename ParamType>
ValidateSamplerParameterBase(Context * context,GLuint sampler,GLenum pname,GLsizei bufSize,ParamType * params)5611 bool ValidateSamplerParameterBase(Context *context,
5612                                   GLuint sampler,
5613                                   GLenum pname,
5614                                   GLsizei bufSize,
5615                                   ParamType *params)
5616 {
5617     if (context->getClientMajorVersion() < 3)
5618     {
5619         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5620         return false;
5621     }
5622 
5623     if (!context->isSampler(sampler))
5624     {
5625         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5626         return false;
5627     }
5628 
5629     const GLsizei minBufSize = 1;
5630     if (bufSize >= 0 && bufSize < minBufSize)
5631     {
5632         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5633         return false;
5634     }
5635 
5636     switch (pname)
5637     {
5638         case GL_TEXTURE_WRAP_S:
5639         case GL_TEXTURE_WRAP_T:
5640         case GL_TEXTURE_WRAP_R:
5641             if (!ValidateTextureWrapModeValue(context, params, false))
5642             {
5643                 return false;
5644             }
5645             break;
5646 
5647         case GL_TEXTURE_MIN_FILTER:
5648             if (!ValidateTextureMinFilterValue(context, params, false))
5649             {
5650                 return false;
5651             }
5652             break;
5653 
5654         case GL_TEXTURE_MAG_FILTER:
5655             if (!ValidateTextureMagFilterValue(context, params))
5656             {
5657                 return false;
5658             }
5659             break;
5660 
5661         case GL_TEXTURE_MIN_LOD:
5662         case GL_TEXTURE_MAX_LOD:
5663             // any value is permissible
5664             break;
5665 
5666         case GL_TEXTURE_COMPARE_MODE:
5667             if (!ValidateTextureCompareModeValue(context, params))
5668             {
5669                 return false;
5670             }
5671             break;
5672 
5673         case GL_TEXTURE_COMPARE_FUNC:
5674             if (!ValidateTextureCompareFuncValue(context, params))
5675             {
5676                 return false;
5677             }
5678             break;
5679 
5680         case GL_TEXTURE_SRGB_DECODE_EXT:
5681             if (!ValidateTextureSRGBDecodeValue(context, params))
5682             {
5683                 return false;
5684             }
5685             break;
5686 
5687         default:
5688             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5689             return false;
5690     }
5691 
5692     return true;
5693 }
5694 
5695 template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5696 template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5697 
ValidateGetSamplerParameterBase(Context * context,GLuint sampler,GLenum pname,GLsizei * length)5698 bool ValidateGetSamplerParameterBase(Context *context,
5699                                      GLuint sampler,
5700                                      GLenum pname,
5701                                      GLsizei *length)
5702 {
5703     if (length)
5704     {
5705         *length = 0;
5706     }
5707 
5708     if (context->getClientMajorVersion() < 3)
5709     {
5710         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5711         return false;
5712     }
5713 
5714     if (!context->isSampler(sampler))
5715     {
5716         ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5717         return false;
5718     }
5719 
5720     switch (pname)
5721     {
5722         case GL_TEXTURE_WRAP_S:
5723         case GL_TEXTURE_WRAP_T:
5724         case GL_TEXTURE_WRAP_R:
5725         case GL_TEXTURE_MIN_FILTER:
5726         case GL_TEXTURE_MAG_FILTER:
5727         case GL_TEXTURE_MIN_LOD:
5728         case GL_TEXTURE_MAX_LOD:
5729         case GL_TEXTURE_COMPARE_MODE:
5730         case GL_TEXTURE_COMPARE_FUNC:
5731             break;
5732 
5733         case GL_TEXTURE_SRGB_DECODE_EXT:
5734             if (!context->getExtensions().textureSRGBDecode)
5735             {
5736                 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5737                 return false;
5738             }
5739             break;
5740 
5741         default:
5742             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5743             return false;
5744     }
5745 
5746     if (length)
5747     {
5748         *length = 1;
5749     }
5750     return true;
5751 }
5752 
ValidateGetInternalFormativBase(Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * numParams)5753 bool ValidateGetInternalFormativBase(Context *context,
5754                                      GLenum target,
5755                                      GLenum internalformat,
5756                                      GLenum pname,
5757                                      GLsizei bufSize,
5758                                      GLsizei *numParams)
5759 {
5760     if (numParams)
5761     {
5762         *numParams = 0;
5763     }
5764 
5765     if (context->getClientMajorVersion() < 3)
5766     {
5767         ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5768         return false;
5769     }
5770 
5771     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5772     if (!formatCaps.renderable)
5773     {
5774         context->handleError(InvalidEnum() << "Internal format is not renderable.");
5775         return false;
5776     }
5777 
5778     switch (target)
5779     {
5780         case GL_RENDERBUFFER:
5781             break;
5782 
5783         case GL_TEXTURE_2D_MULTISAMPLE:
5784             if (context->getClientVersion() < ES_3_1)
5785             {
5786                 context->handleError(InvalidOperation()
5787                                      << "Texture target requires at least OpenGL ES 3.1.");
5788                 return false;
5789             }
5790             break;
5791 
5792         default:
5793             ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5794             return false;
5795     }
5796 
5797     if (bufSize < 0)
5798     {
5799         ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5800         return false;
5801     }
5802 
5803     GLsizei maxWriteParams = 0;
5804     switch (pname)
5805     {
5806         case GL_NUM_SAMPLE_COUNTS:
5807             maxWriteParams = 1;
5808             break;
5809 
5810         case GL_SAMPLES:
5811             maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5812             break;
5813 
5814         default:
5815             ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5816             return false;
5817     }
5818 
5819     if (numParams)
5820     {
5821         // glGetInternalFormativ will not overflow bufSize
5822         *numParams = std::min(bufSize, maxWriteParams);
5823     }
5824 
5825     return true;
5826 }
5827 
5828 }  // namespace gl
5829