1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
8 
9 #include "libANGLE/validationES2_autogen.h"
10 
11 #include <cstdint>
12 
13 #include "common/mathutil.h"
14 #include "common/string_utils.h"
15 #include "common/utilities.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/ErrorStrings.h"
18 #include "libANGLE/Fence.h"
19 #include "libANGLE/Framebuffer.h"
20 #include "libANGLE/FramebufferAttachment.h"
21 #include "libANGLE/MemoryObject.h"
22 #include "libANGLE/Renderbuffer.h"
23 #include "libANGLE/Shader.h"
24 #include "libANGLE/Texture.h"
25 #include "libANGLE/Uniform.h"
26 #include "libANGLE/VertexArray.h"
27 #include "libANGLE/formatutils.h"
28 #include "libANGLE/validationES.h"
29 #include "libANGLE/validationES2.h"
30 #include "libANGLE/validationES3_autogen.h"
31 
32 namespace gl
33 {
34 using namespace err;
35 
36 namespace
37 {
38 
IsPartialBlit(const Context * context,const FramebufferAttachment * readBuffer,const FramebufferAttachment * writeBuffer,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1)39 bool IsPartialBlit(const Context *context,
40                    const FramebufferAttachment *readBuffer,
41                    const FramebufferAttachment *writeBuffer,
42                    GLint srcX0,
43                    GLint srcY0,
44                    GLint srcX1,
45                    GLint srcY1,
46                    GLint dstX0,
47                    GLint dstY0,
48                    GLint dstX1,
49                    GLint dstY1)
50 {
51     const Extents &writeSize = writeBuffer->getSize();
52     const Extents &readSize  = readBuffer->getSize();
53 
54     if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
55         dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
56     {
57         return true;
58     }
59 
60     if (context->getState().isScissorTestEnabled())
61     {
62         const Rectangle &scissor = context->getState().getScissor();
63         return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
64                scissor.height < writeSize.height;
65     }
66 
67     return false;
68 }
69 
IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)70 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
71 {
72     // Table 1.1 from the CHROMIUM_copy_texture spec
73     switch (GetUnsizedFormat(internalFormat))
74     {
75         case GL_RED:
76         case GL_ALPHA:
77         case GL_LUMINANCE:
78         case GL_LUMINANCE_ALPHA:
79         case GL_RGB:
80         case GL_RGBA:
81         case GL_RGB8:
82         case GL_RGBA8:
83         case GL_BGRA_EXT:
84         case GL_BGRA8_EXT:
85             return true;
86 
87         default:
88             return false;
89     }
90 }
91 
IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)92 bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
93 {
94     return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
95 }
96 
IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)97 bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
98 {
99     // Table 1.0 from the CHROMIUM_copy_texture spec
100     switch (internalFormat)
101     {
102         case GL_RGB:
103         case GL_RGBA:
104         case GL_RGB8:
105         case GL_RGBA8:
106         case GL_BGRA_EXT:
107         case GL_BGRA8_EXT:
108         case GL_SRGB_EXT:
109         case GL_SRGB_ALPHA_EXT:
110         case GL_R8:
111         case GL_R8UI:
112         case GL_RG8:
113         case GL_RG8UI:
114         case GL_SRGB8:
115         case GL_RGB565:
116         case GL_RGB8UI:
117         case GL_RGB10_A2:
118         case GL_SRGB8_ALPHA8:
119         case GL_RGB5_A1:
120         case GL_RGBA4:
121         case GL_RGBA8UI:
122         case GL_RGB9_E5:
123         case GL_R16F:
124         case GL_R32F:
125         case GL_RG16F:
126         case GL_RG32F:
127         case GL_RGB16F:
128         case GL_RGB32F:
129         case GL_RGBA16F:
130         case GL_RGBA32F:
131         case GL_R11F_G11F_B10F:
132         case GL_LUMINANCE:
133         case GL_LUMINANCE_ALPHA:
134         case GL_ALPHA:
135             return true;
136 
137         default:
138             return false;
139     }
140 }
141 
IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)142 bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
143 {
144     return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
145 }
146 
IsValidCopyTextureDestinationFormatType(const Context * context,GLint internalFormat,GLenum type)147 bool IsValidCopyTextureDestinationFormatType(const Context *context,
148                                              GLint internalFormat,
149                                              GLenum type)
150 {
151     if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
152     {
153         context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
154         return false;
155     }
156 
157     if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
158     {
159         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
160         return false;
161     }
162 
163     const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
164     if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
165     {
166         context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
167         return false;
168     }
169 
170     return true;
171 }
172 
IsValidCopyTextureDestinationTargetEnum(const Context * context,TextureTarget target)173 bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
174 {
175     switch (target)
176     {
177         case TextureTarget::_2D:
178         case TextureTarget::CubeMapNegativeX:
179         case TextureTarget::CubeMapNegativeY:
180         case TextureTarget::CubeMapNegativeZ:
181         case TextureTarget::CubeMapPositiveX:
182         case TextureTarget::CubeMapPositiveY:
183         case TextureTarget::CubeMapPositiveZ:
184             return true;
185 
186         case TextureTarget::Rectangle:
187             return context->getExtensions().textureRectangle;
188 
189         default:
190             return false;
191     }
192 }
193 
IsValidCopyTextureDestinationTarget(const Context * context,TextureType textureType,TextureTarget target)194 bool IsValidCopyTextureDestinationTarget(const Context *context,
195                                          TextureType textureType,
196                                          TextureTarget target)
197 {
198     return TextureTargetToType(target) == textureType;
199 }
200 
IsValidCopyTextureSourceTarget(const Context * context,TextureType type)201 bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
202 {
203     switch (type)
204     {
205         case TextureType::_2D:
206             return true;
207         case TextureType::Rectangle:
208             return context->getExtensions().textureRectangle;
209         case TextureType::External:
210             return context->getExtensions().eglImageExternalOES;
211         case TextureType::VideoImage:
212             return context->getExtensions().webglVideoTexture;
213         default:
214             return false;
215     }
216 }
217 
IsValidCopyTextureSourceLevel(const Context * context,TextureType type,GLint level)218 bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level)
219 {
220     if (!ValidMipLevel(context, type, level))
221     {
222         return false;
223     }
224 
225     if (level > 0 && context->getClientVersion() < ES_3_0)
226     {
227         return false;
228     }
229 
230     return true;
231 }
232 
IsValidCopyTextureDestinationLevel(const Context * context,TextureType type,GLint level,GLsizei width,GLsizei height,bool isSubImage)233 bool IsValidCopyTextureDestinationLevel(const Context *context,
234                                         TextureType type,
235                                         GLint level,
236                                         GLsizei width,
237                                         GLsizei height,
238                                         bool isSubImage)
239 {
240     if (!ValidMipLevel(context, type, level))
241     {
242         return false;
243     }
244 
245     if (!ValidImageSizeParameters(context, type, level, width, height, 1, isSubImage))
246     {
247         return false;
248     }
249 
250     const Caps &caps = context->getCaps();
251     switch (type)
252     {
253         case TextureType::_2D:
254             return width <= (caps.max2DTextureSize >> level) &&
255                    height <= (caps.max2DTextureSize >> level);
256         case TextureType::Rectangle:
257             ASSERT(level == 0);
258             return width <= (caps.max2DTextureSize >> level) &&
259                    height <= (caps.max2DTextureSize >> level);
260 
261         case TextureType::CubeMap:
262             return width <= (caps.maxCubeMapTextureSize >> level) &&
263                    height <= (caps.maxCubeMapTextureSize >> level);
264         default:
265             return true;
266     }
267 }
268 
IsValidStencilFunc(GLenum func)269 bool IsValidStencilFunc(GLenum func)
270 {
271     switch (func)
272     {
273         case GL_NEVER:
274         case GL_ALWAYS:
275         case GL_LESS:
276         case GL_LEQUAL:
277         case GL_EQUAL:
278         case GL_GEQUAL:
279         case GL_GREATER:
280         case GL_NOTEQUAL:
281             return true;
282 
283         default:
284             return false;
285     }
286 }
287 
IsValidStencilFace(GLenum face)288 bool IsValidStencilFace(GLenum face)
289 {
290     switch (face)
291     {
292         case GL_FRONT:
293         case GL_BACK:
294         case GL_FRONT_AND_BACK:
295             return true;
296 
297         default:
298             return false;
299     }
300 }
301 
IsValidStencilOp(GLenum op)302 bool IsValidStencilOp(GLenum op)
303 {
304     switch (op)
305     {
306         case GL_ZERO:
307         case GL_KEEP:
308         case GL_REPLACE:
309         case GL_INCR:
310         case GL_DECR:
311         case GL_INVERT:
312         case GL_INCR_WRAP:
313         case GL_DECR_WRAP:
314             return true;
315 
316         default:
317             return false;
318     }
319 }
320 
Valid1to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)321 static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
322 {
323     return (context->getExtensions().textureFloatOES &&
324             (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F ||
325              format == GL_R32F)) ||
326            (context->getExtensions().textureHalfFloat &&
327             (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F ||
328              format == GL_R16F));
329 }
330 
Valid2to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)331 static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
332 {
333     return (context->getExtensions().textureFloatOES &&
334             (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) ||
335            (context->getExtensions().textureHalfFloat &&
336             (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F));
337 }
338 
Valid3to4ComponentFloatColorBufferFormat(const Context * context,GLenum format)339 static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
340 {
341     return (context->getExtensions().textureFloatOES &&
342             (format == GL_RGBA32F || format == GL_RGB32F)) ||
343            (context->getExtensions().textureHalfFloat &&
344             (format == GL_RGBA16F || format == GL_RGB16F));
345 }
346 
Valid4ComponentFloatColorBufferFormat(const Context * context,GLenum format)347 static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
348 {
349     return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) ||
350            (context->getExtensions().textureHalfFloat && format == GL_RGBA16F);
351 }
352 
ValidateES2CopyTexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)353 bool ValidateES2CopyTexImageParameters(const Context *context,
354                                        TextureTarget target,
355                                        GLint level,
356                                        GLenum internalformat,
357                                        bool isSubImage,
358                                        GLint xoffset,
359                                        GLint yoffset,
360                                        GLint x,
361                                        GLint y,
362                                        GLsizei width,
363                                        GLsizei height,
364                                        GLint border)
365 {
366     if (!ValidTexture2DDestinationTarget(context, target))
367     {
368         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
369         return false;
370     }
371 
372     TextureType texType = TextureTargetToType(target);
373     if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
374     {
375         // Error is already handled.
376         return false;
377     }
378 
379     Format textureFormat = Format::Invalid();
380     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
381                                             xoffset, yoffset, 0, x, y, width, height, border,
382                                             &textureFormat))
383     {
384         return false;
385     }
386 
387     const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
388     GLenum colorbufferFormat =
389         framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
390     const auto &formatInfo = *textureFormat.info;
391 
392     ASSERT(!formatInfo.compressed);
393 
394     // [OpenGL ES 2.0.24] table 3.9
395     if (isSubImage)
396     {
397         switch (formatInfo.format)
398         {
399             case GL_ALPHA:
400                 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
401                     colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
402                     colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
403                     !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
404                 {
405                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
406                     return false;
407                 }
408                 break;
409             case GL_LUMINANCE:
410                 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
411                     colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
412                     colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
413                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
414                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
415                     !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
416                 {
417                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
418                     return false;
419                 }
420                 break;
421             case GL_RED_EXT:
422                 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
423                     colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
424                     colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
425                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
426                     colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
427                     colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
428                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
429                     !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
430                 {
431                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
432                     return false;
433                 }
434                 break;
435             case GL_RG_EXT:
436                 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
437                     colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
438                     colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
439                     colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
440                     colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
441                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
442                     !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
443                 {
444                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
445                     return false;
446                 }
447                 break;
448             case GL_RGB:
449                 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
450                     colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
451                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
452                     colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
453                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
454                     colorbufferFormat != GL_BGRX8_ANGLEX &&
455                     !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
456                 {
457                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
458                     return false;
459                 }
460                 break;
461             case GL_LUMINANCE_ALPHA:
462             case GL_RGBA:
463                 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
464                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
465                     colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
466                     !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
467                 {
468                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
469                     return false;
470                 }
471                 break;
472             case GL_DEPTH_COMPONENT:
473             case GL_DEPTH_STENCIL_OES:
474                 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
475                 return false;
476             default:
477                 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
478                 return false;
479         }
480 
481         if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
482         {
483             context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
484             return false;
485         }
486     }
487     else
488     {
489         switch (internalformat)
490         {
491             case GL_ALPHA:
492                 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
493                     colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
494                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
495                     !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
496                 {
497                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
498                     return false;
499                 }
500                 break;
501             case GL_LUMINANCE:
502             case GL_RED_EXT:
503                 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
504                     colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
505                     colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
506                     colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
507                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
508                     !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
509                 {
510                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
511                     return false;
512                 }
513                 break;
514             case GL_RG_EXT:
515                 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
516                     colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
517                     colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
518                     colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
519                     !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
520                 {
521                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
522                     return false;
523                 }
524                 break;
525             case GL_RGB:
526                 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
527                     colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
528                     colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
529                     colorbufferFormat != GL_BGR5_A1_ANGLEX &&
530                     !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
531                 {
532                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
533                     return false;
534                 }
535                 break;
536             case GL_LUMINANCE_ALPHA:
537             case GL_RGBA:
538                 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
539                     colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
540                     colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F &&
541                     !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
542                 {
543                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
544                     return false;
545                 }
546                 break;
547             case GL_DEPTH_COMPONENT:
548             case GL_DEPTH_COMPONENT16:
549             case GL_DEPTH_COMPONENT32_OES:
550                 if (context->getExtensions().depthTextureAny())
551                 {
552                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
553                     return false;
554                 }
555                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
556                 return false;
557             case GL_DEPTH_STENCIL_OES:
558             case GL_DEPTH24_STENCIL8_OES:
559                 if (context->getExtensions().depthTextureAny() ||
560                     context->getExtensions().packedDepthStencilOES ||
561                     context->getExtensions().depthTextureCubeMapOES)
562                 {
563                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
564                     return false;
565                 }
566                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
567                 return false;
568             default:
569                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
570                 return false;
571         }
572     }
573 
574     // If width or height is zero, it is a no-op.  Return false without setting an error.
575     return (width > 0 && height > 0);
576 }
577 
ValidCap(const Context * context,GLenum cap,bool queryOnly)578 bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
579 {
580     switch (cap)
581     {
582         // EXT_multisample_compatibility
583         case GL_MULTISAMPLE_EXT:
584         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
585             return context->getExtensions().multisampleCompatibility;
586 
587         case GL_CULL_FACE:
588         case GL_POLYGON_OFFSET_FILL:
589         case GL_SAMPLE_ALPHA_TO_COVERAGE:
590         case GL_SAMPLE_COVERAGE:
591         case GL_SCISSOR_TEST:
592         case GL_STENCIL_TEST:
593         case GL_DEPTH_TEST:
594         case GL_BLEND:
595         case GL_DITHER:
596             return true;
597 
598         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
599         case GL_RASTERIZER_DISCARD:
600             return (context->getClientMajorVersion() >= 3);
601 
602         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
603         case GL_DEBUG_OUTPUT:
604             return context->getExtensions().debug;
605 
606         case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
607             return queryOnly && context->getExtensions().bindGeneratesResource;
608 
609         case GL_CLIENT_ARRAYS_ANGLE:
610             return queryOnly && context->getExtensions().clientArrays;
611 
612         case GL_FRAMEBUFFER_SRGB_EXT:
613             return context->getExtensions().sRGBWriteControl;
614 
615         case GL_SAMPLE_MASK:
616             return context->getClientVersion() >= Version(3, 1);
617 
618         case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
619             return queryOnly && context->getExtensions().robustResourceInitialization;
620 
621         case GL_TEXTURE_RECTANGLE_ANGLE:
622             return context->getExtensions().webglCompatibility;
623 
624         // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
625         case GL_CLIP_DISTANCE0_EXT:
626         case GL_CLIP_DISTANCE1_EXT:
627         case GL_CLIP_DISTANCE2_EXT:
628         case GL_CLIP_DISTANCE3_EXT:
629         case GL_CLIP_DISTANCE4_EXT:
630         case GL_CLIP_DISTANCE5_EXT:
631         case GL_CLIP_DISTANCE6_EXT:
632         case GL_CLIP_DISTANCE7_EXT:
633             if (context->getExtensions().clipDistanceAPPLE ||
634                 context->getExtensions().clipCullDistanceEXT)
635             {
636                 return true;
637             }
638             break;
639         case GL_SAMPLE_SHADING:
640             return context->getExtensions().sampleShadingOES;
641     }
642 
643     // GLES1 emulation: GLES1-specific caps after this point
644     if (context->getClientVersion().major != 1)
645     {
646         return false;
647     }
648 
649     switch (cap)
650     {
651         case GL_ALPHA_TEST:
652         case GL_VERTEX_ARRAY:
653         case GL_NORMAL_ARRAY:
654         case GL_COLOR_ARRAY:
655         case GL_TEXTURE_COORD_ARRAY:
656         case GL_TEXTURE_2D:
657         case GL_LIGHTING:
658         case GL_LIGHT0:
659         case GL_LIGHT1:
660         case GL_LIGHT2:
661         case GL_LIGHT3:
662         case GL_LIGHT4:
663         case GL_LIGHT5:
664         case GL_LIGHT6:
665         case GL_LIGHT7:
666         case GL_NORMALIZE:
667         case GL_RESCALE_NORMAL:
668         case GL_COLOR_MATERIAL:
669         case GL_CLIP_PLANE0:
670         case GL_CLIP_PLANE1:
671         case GL_CLIP_PLANE2:
672         case GL_CLIP_PLANE3:
673         case GL_CLIP_PLANE4:
674         case GL_CLIP_PLANE5:
675         case GL_FOG:
676         case GL_POINT_SMOOTH:
677         case GL_LINE_SMOOTH:
678         case GL_COLOR_LOGIC_OP:
679             return context->getClientVersion() < Version(2, 0);
680         case GL_POINT_SIZE_ARRAY_OES:
681             return context->getClientVersion() < Version(2, 0) &&
682                    context->getExtensions().pointSizeArrayOES;
683         case GL_TEXTURE_CUBE_MAP:
684             return context->getClientVersion() < Version(2, 0) &&
685                    context->getExtensions().textureCubeMapOES;
686         case GL_POINT_SPRITE_OES:
687             return context->getClientVersion() < Version(2, 0) &&
688                    context->getExtensions().pointSpriteOES;
689         default:
690             return false;
691     }
692 }
693 
694 // Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
695 // 3.1.
IsValidESSLCharacter(unsigned char c)696 bool IsValidESSLCharacter(unsigned char c)
697 {
698     // Printing characters are valid except " $ ` @ \ ' DEL.
699     if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
700         c != '\'')
701     {
702         return true;
703     }
704 
705     // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
706     if (c >= 9 && c <= 13)
707     {
708         return true;
709     }
710 
711     return false;
712 }
713 
IsValidESSLString(const char * str,size_t len)714 bool IsValidESSLString(const char *str, size_t len)
715 {
716     for (size_t i = 0; i < len; i++)
717     {
718         if (!IsValidESSLCharacter(str[i]))
719         {
720             return false;
721         }
722     }
723 
724     return true;
725 }
726 
ValidateWebGLNamePrefix(const Context * context,const GLchar * name)727 bool ValidateWebGLNamePrefix(const Context *context, const GLchar *name)
728 {
729     ASSERT(context->isWebGL());
730 
731     // WebGL 1.0 [Section 6.16] GLSL Constructs
732     // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
733     if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
734     {
735         context->validationError(GL_INVALID_OPERATION, kWebglBindAttribLocationReservedPrefix);
736         return false;
737     }
738 
739     return true;
740 }
741 
ValidateWebGLNameLength(const Context * context,size_t length)742 bool ValidateWebGLNameLength(const Context *context, size_t length)
743 {
744     ASSERT(context->isWebGL());
745 
746     if (context->isWebGL1() && length > 256)
747     {
748         // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
749         // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
750         // locations.
751         context->validationError(GL_INVALID_VALUE, kWebglNameLengthLimitExceeded);
752 
753         return false;
754     }
755     else if (length > 1024)
756     {
757         // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
758         // uniform and attribute locations.
759         context->validationError(GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded);
760         return false;
761     }
762 
763     return true;
764 }
765 
ValidBlendFunc(const Context * context,GLenum val)766 bool ValidBlendFunc(const Context *context, GLenum val)
767 {
768     const Extensions &ext = context->getExtensions();
769 
770     // these are always valid for src and dst.
771     switch (val)
772     {
773         case GL_ZERO:
774         case GL_ONE:
775         case GL_SRC_COLOR:
776         case GL_ONE_MINUS_SRC_COLOR:
777         case GL_DST_COLOR:
778         case GL_ONE_MINUS_DST_COLOR:
779         case GL_SRC_ALPHA:
780         case GL_ONE_MINUS_SRC_ALPHA:
781         case GL_DST_ALPHA:
782         case GL_ONE_MINUS_DST_ALPHA:
783         case GL_CONSTANT_COLOR:
784         case GL_ONE_MINUS_CONSTANT_COLOR:
785         case GL_CONSTANT_ALPHA:
786         case GL_ONE_MINUS_CONSTANT_ALPHA:
787             return true;
788 
789         // EXT_blend_func_extended.
790         case GL_SRC1_COLOR_EXT:
791         case GL_SRC1_ALPHA_EXT:
792         case GL_ONE_MINUS_SRC1_COLOR_EXT:
793         case GL_ONE_MINUS_SRC1_ALPHA_EXT:
794         case GL_SRC_ALPHA_SATURATE_EXT:
795             return ext.blendFuncExtended;
796 
797         default:
798             return false;
799     }
800 }
801 
ValidSrcBlendFunc(const Context * context,GLenum val)802 bool ValidSrcBlendFunc(const Context *context, GLenum val)
803 {
804     if (ValidBlendFunc(context, val))
805         return true;
806 
807     if (val == GL_SRC_ALPHA_SATURATE)
808         return true;
809 
810     return false;
811 }
812 
ValidDstBlendFunc(const Context * context,GLenum val)813 bool ValidDstBlendFunc(const Context *context, GLenum val)
814 {
815     if (ValidBlendFunc(context, val))
816         return true;
817 
818     if (val == GL_SRC_ALPHA_SATURATE)
819     {
820         if (context->getClientMajorVersion() >= 3)
821             return true;
822     }
823 
824     return false;
825 }
826 
ValidateES2TexImageParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)827 bool ValidateES2TexImageParameters(const Context *context,
828                                    TextureTarget target,
829                                    GLint level,
830                                    GLenum internalformat,
831                                    bool isCompressed,
832                                    bool isSubImage,
833                                    GLint xoffset,
834                                    GLint yoffset,
835                                    GLsizei width,
836                                    GLsizei height,
837                                    GLint border,
838                                    GLenum format,
839                                    GLenum type,
840                                    GLsizei imageSize,
841                                    const void *pixels)
842 {
843     if (!ValidTexture2DDestinationTarget(context, target))
844     {
845         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
846         return false;
847     }
848 
849     return ValidateES2TexImageParametersBase(context, target, level, internalformat, isCompressed,
850                                              isSubImage, xoffset, yoffset, width, height, border,
851                                              format, type, imageSize, pixels);
852 }
853 
854 }  // anonymous namespace
855 
ValidateES2TexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)856 bool ValidateES2TexImageParametersBase(const Context *context,
857                                        TextureTarget target,
858                                        GLint level,
859                                        GLenum internalformat,
860                                        bool isCompressed,
861                                        bool isSubImage,
862                                        GLint xoffset,
863                                        GLint yoffset,
864                                        GLsizei width,
865                                        GLsizei height,
866                                        GLint border,
867                                        GLenum format,
868                                        GLenum type,
869                                        GLsizei imageSize,
870                                        const void *pixels)
871 {
872 
873     TextureType texType = TextureTargetToType(target);
874     if (!ValidImageSizeParameters(context, texType, level, width, height, 1, isSubImage))
875     {
876         // Error already handled.
877         return false;
878     }
879 
880     if (!ValidMipLevel(context, texType, level))
881     {
882         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
883         return false;
884     }
885 
886     if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
887         std::numeric_limits<GLsizei>::max() - yoffset < height)
888     {
889         context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
890         return false;
891     }
892 
893     const Caps &caps = context->getCaps();
894 
895     switch (texType)
896     {
897         case TextureType::_2D:
898         case TextureType::External:
899         case TextureType::VideoImage:
900             if (width > (caps.max2DTextureSize >> level) ||
901                 height > (caps.max2DTextureSize >> level))
902             {
903                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
904                 return false;
905             }
906             break;
907 
908         case TextureType::Rectangle:
909             ASSERT(level == 0);
910             if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
911             {
912                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
913                 return false;
914             }
915             if (isCompressed)
916             {
917                 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
918                 return false;
919             }
920             break;
921 
922         case TextureType::CubeMap:
923             if (!isSubImage && width != height)
924             {
925                 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
926                 return false;
927             }
928 
929             if (width > (caps.maxCubeMapTextureSize >> level) ||
930                 height > (caps.maxCubeMapTextureSize >> level))
931             {
932                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
933                 return false;
934             }
935             break;
936 
937         default:
938             context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
939             return false;
940     }
941 
942     Texture *texture = context->getTextureByType(texType);
943     if (!texture)
944     {
945         context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
946         return false;
947     }
948 
949     // Verify zero border
950     if (border != 0)
951     {
952         context->validationError(GL_INVALID_VALUE, kInvalidBorder);
953         return false;
954     }
955 
956     bool nonEqualFormatsAllowed = false;
957 
958     if (isCompressed)
959     {
960         GLenum actualInternalFormat =
961             isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
962                        : internalformat;
963 
964         const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat);
965 
966         if (!internalFormatInfo.compressed)
967         {
968             context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
969             return false;
970         }
971 
972         if (!internalFormatInfo.textureSupport(context->getClientVersion(),
973                                                context->getExtensions()))
974         {
975             context->validationError(GL_INVALID_ENUM, kInvalidInternalFormat);
976             return false;
977         }
978 
979         if (isSubImage)
980         {
981             // From the OES_compressed_ETC1_RGB8_texture spec:
982             //
983             // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
984             // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
985             // ETC1_RGB8_OES.
986             //
987             // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
988             if (actualInternalFormat == GL_ETC1_RGB8_OES &&
989                 !context->getExtensions().compressedETC1RGB8SubTexture)
990             {
991                 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
992                 return false;
993             }
994 
995             if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0,
996                                              width, height, 1, texture->getWidth(target, level),
997                                              texture->getHeight(target, level),
998                                              texture->getDepth(target, level)))
999             {
1000                 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1001                 return false;
1002             }
1003 
1004             if (format != actualInternalFormat)
1005             {
1006                 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1007                 return false;
1008             }
1009         }
1010         else
1011         {
1012             if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1))
1013             {
1014                 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1015                 return false;
1016             }
1017         }
1018     }
1019     else
1020     {
1021         // validate <type> by itself (used as secondary key below)
1022         switch (type)
1023         {
1024             case GL_UNSIGNED_BYTE:
1025             case GL_UNSIGNED_SHORT_5_6_5:
1026             case GL_UNSIGNED_SHORT_4_4_4_4:
1027             case GL_UNSIGNED_SHORT_5_5_5_1:
1028             case GL_UNSIGNED_SHORT:
1029             case GL_UNSIGNED_INT:
1030             case GL_UNSIGNED_INT_24_8_OES:
1031             case GL_HALF_FLOAT_OES:
1032             case GL_FLOAT:
1033                 break;
1034             case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1035                 if (!context->getExtensions().textureFormat2101010REV)
1036                 {
1037                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1038                     return false;
1039                 }
1040                 break;
1041             default:
1042                 context->validationError(GL_INVALID_ENUM, kInvalidType);
1043                 return false;
1044         }
1045 
1046         // validate <format> + <type> combinations
1047         // - invalid <format> -> sets INVALID_ENUM
1048         // - invalid <format>+<type> combination -> sets INVALID_OPERATION
1049         switch (format)
1050         {
1051             case GL_ALPHA:
1052             case GL_LUMINANCE:
1053             case GL_LUMINANCE_ALPHA:
1054                 switch (type)
1055                 {
1056                     case GL_UNSIGNED_BYTE:
1057                     case GL_FLOAT:
1058                     case GL_HALF_FLOAT_OES:
1059                         break;
1060                     default:
1061                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1062                         return false;
1063                 }
1064                 break;
1065             case GL_RED:
1066             case GL_RG:
1067                 if (!context->getExtensions().textureRG)
1068                 {
1069                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1070                     return false;
1071                 }
1072                 switch (type)
1073                 {
1074                     case GL_UNSIGNED_BYTE:
1075                         break;
1076                     case GL_FLOAT:
1077                         if (!context->getExtensions().textureFloatOES)
1078                         {
1079                             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1080                             return false;
1081                         }
1082                         break;
1083                     case GL_HALF_FLOAT_OES:
1084                         if (!context->getExtensions().textureFloatOES &&
1085                             !context->getExtensions().textureHalfFloat)
1086                         {
1087                             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1088                             return false;
1089                         }
1090                         break;
1091                     case GL_SHORT:
1092                     case GL_UNSIGNED_SHORT:
1093                         if (!context->getExtensions().textureNorm16)
1094                         {
1095                             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1096                             return false;
1097                         }
1098                         break;
1099                     default:
1100                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1101                         return false;
1102                 }
1103                 break;
1104             case GL_RGB:
1105                 switch (type)
1106                 {
1107                     case GL_UNSIGNED_BYTE:
1108                     case GL_UNSIGNED_SHORT_5_6_5:
1109                     case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1110                     case GL_FLOAT:
1111                     case GL_HALF_FLOAT_OES:
1112                         break;
1113                     case GL_SHORT:
1114                     case GL_UNSIGNED_SHORT:
1115                         if (!context->getExtensions().textureNorm16)
1116                         {
1117                             context->validationError(GL_INVALID_OPERATION,
1118                                                      kMismatchedTypeAndFormat);
1119                             return false;
1120                         }
1121                         break;
1122                     default:
1123                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1124                         return false;
1125                 }
1126                 break;
1127             case GL_RGBA:
1128                 switch (type)
1129                 {
1130                     case GL_UNSIGNED_BYTE:
1131                     case GL_UNSIGNED_SHORT_4_4_4_4:
1132                     case GL_UNSIGNED_SHORT_5_5_5_1:
1133                     case GL_FLOAT:
1134                     case GL_HALF_FLOAT_OES:
1135                     case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
1136                         break;
1137                     case GL_SHORT:
1138                     case GL_UNSIGNED_SHORT:
1139                         if (!context->getExtensions().textureNorm16)
1140                         {
1141                             context->validationError(GL_INVALID_OPERATION,
1142                                                      kMismatchedTypeAndFormat);
1143                             return false;
1144                         }
1145                         break;
1146                     default:
1147                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1148                         return false;
1149                 }
1150                 break;
1151             case GL_BGRA_EXT:
1152                 if (!context->getExtensions().textureFormatBGRA8888)
1153                 {
1154                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1155                     return false;
1156                 }
1157                 switch (type)
1158                 {
1159                     case GL_UNSIGNED_BYTE:
1160                         break;
1161                     default:
1162                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1163                         return false;
1164                 }
1165                 break;
1166             case GL_SRGB_EXT:
1167             case GL_SRGB_ALPHA_EXT:
1168                 if (!context->getExtensions().sRGB)
1169                 {
1170                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1171                     return false;
1172                 }
1173                 switch (type)
1174                 {
1175                     case GL_UNSIGNED_BYTE:
1176                         break;
1177                     default:
1178                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1179                         return false;
1180                 }
1181                 break;
1182             case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are
1183                                                    // handled below
1184             case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1185             case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1186             case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1187                 break;
1188             case GL_DEPTH_COMPONENT:
1189                 switch (type)
1190                 {
1191                     case GL_UNSIGNED_SHORT:
1192                     case GL_UNSIGNED_INT:
1193                         break;
1194                     case GL_FLOAT:
1195                         if (!context->getExtensions().depthBufferFloat2NV)
1196                         {
1197                             context->validationError(GL_INVALID_OPERATION,
1198                                                      kMismatchedTypeAndFormat);
1199                             return false;
1200                         }
1201                         break;
1202                     default:
1203                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1204                         return false;
1205                 }
1206                 break;
1207             case GL_DEPTH_STENCIL_OES:
1208                 switch (type)
1209                 {
1210                     case GL_UNSIGNED_INT_24_8_OES:
1211                         break;
1212                     default:
1213                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1214                         return false;
1215                 }
1216                 break;
1217             case GL_STENCIL_INDEX:
1218                 switch (type)
1219                 {
1220                     case GL_UNSIGNED_BYTE:
1221                         break;
1222                     default:
1223                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1224                         return false;
1225                 }
1226                 break;
1227             default:
1228                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1229                 return false;
1230         }
1231 
1232         switch (format)
1233         {
1234             case GL_DEPTH_COMPONENT:
1235             case GL_DEPTH_STENCIL_OES:
1236                 if (!context->getExtensions().depthTextureANGLE &&
1237                     !((context->getExtensions().packedDepthStencilOES ||
1238                        context->getExtensions().depthTextureCubeMapOES) &&
1239                       context->getExtensions().depthTextureOES))
1240                 {
1241                     context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1242                     return false;
1243                 }
1244 
1245                 switch (target)
1246                 {
1247                     case TextureTarget::_2D:
1248                         break;
1249                     case TextureTarget::CubeMapNegativeX:
1250                     case TextureTarget::CubeMapNegativeY:
1251                     case TextureTarget::CubeMapNegativeZ:
1252                     case TextureTarget::CubeMapPositiveX:
1253                     case TextureTarget::CubeMapPositiveY:
1254                     case TextureTarget::CubeMapPositiveZ:
1255                         if (!context->getExtensions().depthTextureCubeMapOES)
1256                         {
1257                             context->validationError(GL_INVALID_OPERATION,
1258                                                      kMismatchedTargetAndFormat);
1259                             return false;
1260                         }
1261                         break;
1262                     default:
1263                         context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1264                         return false;
1265                 }
1266 
1267                 // OES_depth_texture supports loading depth data and multiple levels,
1268                 // but ANGLE_depth_texture does not
1269                 if (!context->getExtensions().depthTextureOES)
1270                 {
1271                     if (pixels != nullptr)
1272                     {
1273                         context->validationError(GL_INVALID_OPERATION, kPixelDataNotNull);
1274                         return false;
1275                     }
1276                     if (level != 0)
1277                     {
1278                         context->validationError(GL_INVALID_OPERATION, kLevelNotZero);
1279                         return false;
1280                     }
1281                 }
1282                 break;
1283             case GL_STENCIL_INDEX:
1284                 if (!context->getExtensions().stencilIndex8)
1285                 {
1286                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1287                     return false;
1288                 }
1289 
1290                 switch (target)
1291                 {
1292                     case TextureTarget::_2D:
1293                     case TextureTarget::_2DArray:
1294                     case TextureTarget::CubeMapNegativeX:
1295                     case TextureTarget::CubeMapNegativeY:
1296                     case TextureTarget::CubeMapNegativeZ:
1297                     case TextureTarget::CubeMapPositiveX:
1298                     case TextureTarget::CubeMapPositiveY:
1299                     case TextureTarget::CubeMapPositiveZ:
1300                         break;
1301                     default:
1302                         context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1303                         return false;
1304                 }
1305 
1306                 if (internalformat != GL_STENCIL_INDEX8)
1307                 {
1308                     context->validationError(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
1309                     return false;
1310                 }
1311                 break;
1312             default:
1313                 break;
1314         }
1315 
1316         if (!isSubImage)
1317         {
1318             switch (internalformat)
1319             {
1320                 // Core ES 2.0 formats
1321                 case GL_ALPHA:
1322                 case GL_LUMINANCE:
1323                 case GL_LUMINANCE_ALPHA:
1324                 case GL_RGB:
1325                 case GL_RGBA:
1326                     break;
1327 
1328                 case GL_RGBA32F:
1329                     if (!context->getExtensions().colorBufferFloatRGBA)
1330                     {
1331                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1332                         return false;
1333                     }
1334 
1335                     nonEqualFormatsAllowed = true;
1336 
1337                     if (type != GL_FLOAT)
1338                     {
1339                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1340                         return false;
1341                     }
1342                     if (format != GL_RGBA)
1343                     {
1344                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1345                         return false;
1346                     }
1347                     break;
1348 
1349                 case GL_RGB32F:
1350                     if (!context->getExtensions().colorBufferFloatRGB)
1351                     {
1352                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1353                         return false;
1354                     }
1355 
1356                     nonEqualFormatsAllowed = true;
1357 
1358                     if (type != GL_FLOAT)
1359                     {
1360                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1361                         return false;
1362                     }
1363                     if (format != GL_RGB)
1364                     {
1365                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1366                         return false;
1367                     }
1368                     break;
1369 
1370                 case GL_BGRA_EXT:
1371                     if (!context->getExtensions().textureFormatBGRA8888)
1372                     {
1373                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1374                         return false;
1375                     }
1376                     break;
1377 
1378                 case GL_DEPTH_COMPONENT:
1379                     if (!(context->getExtensions().depthTextureAny()))
1380                     {
1381                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1382                         return false;
1383                     }
1384                     break;
1385 
1386                 case GL_DEPTH_STENCIL:
1387                     if (!(context->getExtensions().depthTextureANGLE ||
1388                           context->getExtensions().packedDepthStencilOES ||
1389                           context->getExtensions().depthTextureCubeMapOES))
1390                     {
1391                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1392                         return false;
1393                     }
1394                     break;
1395 
1396                 case GL_STENCIL_INDEX8:
1397                     if (!context->getExtensions().stencilIndex8)
1398                     {
1399                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1400                         return false;
1401                     }
1402                     break;
1403 
1404                 case GL_RED:
1405                 case GL_RG:
1406                     if (!context->getExtensions().textureRG)
1407                     {
1408                         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1409                         return false;
1410                     }
1411                     break;
1412 
1413                 case GL_SRGB_EXT:
1414                 case GL_SRGB_ALPHA_EXT:
1415                     if (!context->getExtensions().sRGB)
1416                     {
1417                         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1418                         return false;
1419                     }
1420                     break;
1421 
1422                 case GL_RGB10_A2_EXT:
1423                     if (!context->getExtensions().textureFormat2101010REV)
1424                     {
1425                         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1426                         return false;
1427                     }
1428 
1429                     if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
1430                     {
1431                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
1432                         return false;
1433                     }
1434 
1435                     nonEqualFormatsAllowed = true;
1436 
1437                     break;
1438 
1439                 case GL_RGB5_A1:
1440                     if (context->getExtensions().textureFormat2101010REV &&
1441                         type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
1442                     {
1443                         nonEqualFormatsAllowed = true;
1444                     }
1445 
1446                     break;
1447 
1448                 case GL_R16_EXT:
1449                 case GL_RG16_EXT:
1450                 case GL_RGB16_EXT:
1451                 case GL_RGBA16_EXT:
1452                 case GL_R16_SNORM_EXT:
1453                 case GL_RG16_SNORM_EXT:
1454                 case GL_RGB16_SNORM_EXT:
1455                 case GL_RGBA16_SNORM_EXT:
1456                     if (!context->getExtensions().textureNorm16)
1457                     {
1458                         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1459                         return false;
1460                     }
1461                     break;
1462                 default:
1463                     context->validationError(GL_INVALID_VALUE, kInvalidInternalFormat);
1464                     return false;
1465             }
1466         }
1467 
1468         if (type == GL_FLOAT)
1469         {
1470             if (!context->getExtensions().textureFloatOES)
1471             {
1472                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1473                 return false;
1474             }
1475         }
1476         else if (type == GL_HALF_FLOAT_OES)
1477         {
1478             if (!context->getExtensions().textureHalfFloat)
1479             {
1480                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1481                 return false;
1482             }
1483         }
1484     }
1485 
1486     if (isSubImage)
1487     {
1488         const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
1489         if (textureInternalFormat.internalFormat == GL_NONE)
1490         {
1491             context->validationError(GL_INVALID_OPERATION, kInvalidTextureLevel);
1492             return false;
1493         }
1494 
1495         if (format != textureInternalFormat.format)
1496         {
1497             context->validationError(GL_INVALID_OPERATION, err::kTextureFormatMismatch);
1498             return false;
1499         }
1500 
1501         if (context->getExtensions().webglCompatibility)
1502         {
1503             if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
1504                 textureInternalFormat.sizedInternalFormat)
1505             {
1506                 context->validationError(GL_INVALID_OPERATION, kTextureTypeMismatch);
1507                 return false;
1508             }
1509         }
1510 
1511         if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1512             static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
1513         {
1514             context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
1515             return false;
1516         }
1517 
1518         if (width > 0 && height > 0 && pixels == nullptr &&
1519             context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
1520         {
1521             context->validationError(GL_INVALID_VALUE, kPixelDataNull);
1522             return false;
1523         }
1524     }
1525     else
1526     {
1527         if (texture->getImmutableFormat())
1528         {
1529             context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1530             return false;
1531         }
1532     }
1533 
1534     // From GL_CHROMIUM_color_buffer_float_rgb[a]:
1535     // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
1536     // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
1537     // internalformat parameter and format parameter of TexImage2D must match is lifted for this
1538     // case.
1539     if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
1540     {
1541         context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
1542         return false;
1543     }
1544 
1545     GLenum sizeCheckFormat = isSubImage ? format : internalformat;
1546     return ValidImageDataSize(context, texType, width, height, 1, sizeCheckFormat, type, pixels,
1547                               imageSize);
1548 }
1549 
ValidateES2TexStorageParametersBase(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)1550 bool ValidateES2TexStorageParametersBase(const Context *context,
1551                                          TextureType target,
1552                                          GLsizei levels,
1553                                          GLenum internalformat,
1554                                          GLsizei width,
1555                                          GLsizei height)
1556 {
1557     if (target != TextureType::_2D && target != TextureType::CubeMap &&
1558         target != TextureType::Rectangle)
1559     {
1560         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1561         return false;
1562     }
1563 
1564     if (width < 1 || height < 1 || levels < 1)
1565     {
1566         context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
1567         return false;
1568     }
1569 
1570     if (target == TextureType::CubeMap && width != height)
1571     {
1572         context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1573         return false;
1574     }
1575 
1576     if (levels != 1 && levels != log2(std::max(width, height)) + 1)
1577     {
1578         context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1579         return false;
1580     }
1581 
1582     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1583     if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
1584     {
1585         context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1586         return false;
1587     }
1588 
1589     const Caps &caps = context->getCaps();
1590 
1591     switch (target)
1592     {
1593         case TextureType::_2D:
1594             if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1595             {
1596                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1597                 return false;
1598             }
1599             break;
1600         case TextureType::Rectangle:
1601             if (levels != 1)
1602             {
1603                 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
1604                 return false;
1605             }
1606 
1607             if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1608             {
1609                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1610                 return false;
1611             }
1612             if (formatInfo.compressed)
1613             {
1614                 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
1615                 return false;
1616             }
1617             break;
1618         case TextureType::CubeMap:
1619             if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize)
1620             {
1621                 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1622                 return false;
1623             }
1624             break;
1625         default:
1626             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1627             return false;
1628     }
1629 
1630     if (levels != 1 && !context->getExtensions().textureNPOTOES)
1631     {
1632         if (!isPow2(width) || !isPow2(height))
1633         {
1634             context->validationError(GL_INVALID_OPERATION, kDimensionsMustBePow2);
1635             return false;
1636         }
1637     }
1638 
1639     switch (internalformat)
1640     {
1641         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1642         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1643             if (!context->getExtensions().textureCompressionDXT1)
1644             {
1645                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1646                 return false;
1647             }
1648             break;
1649         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1650             if (!context->getExtensions().textureCompressionDXT3)
1651             {
1652                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1653                 return false;
1654             }
1655             break;
1656         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1657             if (!context->getExtensions().textureCompressionDXT5)
1658             {
1659                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1660                 return false;
1661             }
1662             break;
1663         case GL_ETC1_RGB8_OES:
1664             if (!context->getExtensions().compressedETC1RGB8TextureOES)
1665             {
1666                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1667                 return false;
1668             }
1669             break;
1670         case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1671         case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1672         case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1673         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1674         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1675             if (!context->getExtensions().lossyETCDecode)
1676             {
1677                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1678                 return false;
1679             }
1680             break;
1681         case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
1682         case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
1683         case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
1684         case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
1685             if (!context->getExtensions().compressedTexturePVRTC)
1686             {
1687                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1688                 return false;
1689             }
1690             break;
1691         case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
1692         case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
1693         case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
1694         case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
1695             if (!context->getExtensions().compressedTexturePVRTCsRGB)
1696             {
1697                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1698                 return false;
1699             }
1700             break;
1701         case GL_RGBA32F_EXT:
1702         case GL_RGB32F_EXT:
1703         case GL_ALPHA32F_EXT:
1704         case GL_LUMINANCE32F_EXT:
1705         case GL_LUMINANCE_ALPHA32F_EXT:
1706             if (!context->getExtensions().textureFloatOES)
1707             {
1708                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1709                 return false;
1710             }
1711             break;
1712         case GL_RGBA16F_EXT:
1713         case GL_RGB16F_EXT:
1714         case GL_ALPHA16F_EXT:
1715         case GL_LUMINANCE16F_EXT:
1716         case GL_LUMINANCE_ALPHA16F_EXT:
1717             if (!context->getExtensions().textureHalfFloat)
1718             {
1719                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1720                 return false;
1721             }
1722             break;
1723         case GL_R8_EXT:
1724         case GL_RG8_EXT:
1725             if (!context->getExtensions().textureRG)
1726             {
1727                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1728                 return false;
1729             }
1730             break;
1731         case GL_R16F_EXT:
1732         case GL_RG16F_EXT:
1733             if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
1734             {
1735                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1736                 return false;
1737             }
1738             break;
1739         case GL_R32F_EXT:
1740         case GL_RG32F_EXT:
1741             if (!context->getExtensions().textureRG || !context->getExtensions().textureFloatOES)
1742             {
1743                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1744                 return false;
1745             }
1746             break;
1747         case GL_DEPTH_COMPONENT16:
1748         case GL_DEPTH_COMPONENT32_OES:
1749             if (!(context->getExtensions().depthTextureAny()))
1750             {
1751                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1752                 return false;
1753             }
1754 
1755             switch (target)
1756             {
1757                 case TextureType::_2D:
1758                     break;
1759                 case TextureType::CubeMap:
1760                     if (!context->getExtensions().depthTextureCubeMapOES)
1761                     {
1762                         context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1763                         return false;
1764                     }
1765                     break;
1766                 default:
1767                     context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1768                     return false;
1769             }
1770 
1771             // ANGLE_depth_texture only supports 1-level textures
1772             if (!context->getExtensions().depthTextureOES)
1773             {
1774                 if (levels != 1)
1775                 {
1776                     context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1777                     return false;
1778                 }
1779             }
1780             break;
1781         case GL_DEPTH24_STENCIL8_OES:
1782             if (!(context->getExtensions().depthTextureANGLE ||
1783                   ((context->getExtensions().packedDepthStencilOES ||
1784                     context->getExtensions().depthTextureCubeMapOES) &&
1785                    context->getExtensions().textureStorage)))
1786             {
1787                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1788                 return false;
1789             }
1790 
1791             switch (target)
1792             {
1793                 case TextureType::_2D:
1794                     break;
1795                 case TextureType::CubeMap:
1796                     if (!context->getExtensions().depthTextureCubeMapOES)
1797                     {
1798                         context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1799                         return false;
1800                     }
1801                     break;
1802                 default:
1803                     context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
1804                     return false;
1805             }
1806 
1807             if (!context->getExtensions().packedDepthStencilOES &&
1808                 !context->getExtensions().depthTextureCubeMapOES)
1809             {
1810                 // ANGLE_depth_texture only supports 1-level textures
1811                 if (levels != 1)
1812                 {
1813                     context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1814                     return false;
1815                 }
1816             }
1817             break;
1818 
1819         default:
1820             break;
1821     }
1822 
1823     Texture *texture = context->getTextureByType(target);
1824     if (!texture || texture->id().value == 0)
1825     {
1826         context->validationError(GL_INVALID_OPERATION, kMissingTexture);
1827         return false;
1828     }
1829 
1830     if (texture->getImmutableFormat())
1831     {
1832         context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1833         return false;
1834     }
1835 
1836     return true;
1837 }
1838 
ValidateDiscardFramebufferEXT(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)1839 bool ValidateDiscardFramebufferEXT(const Context *context,
1840                                    GLenum target,
1841                                    GLsizei numAttachments,
1842                                    const GLenum *attachments)
1843 {
1844     if (!context->getExtensions().discardFramebuffer)
1845     {
1846         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1847         return false;
1848     }
1849 
1850     bool defaultFramebuffer = false;
1851 
1852     switch (target)
1853     {
1854         case GL_FRAMEBUFFER:
1855             defaultFramebuffer =
1856                 (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
1857             break;
1858         default:
1859             context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1860             return false;
1861     }
1862 
1863     return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1864                                           defaultFramebuffer);
1865 }
1866 
ValidateBindVertexArrayOES(const Context * context,VertexArrayID array)1867 bool ValidateBindVertexArrayOES(const Context *context, VertexArrayID array)
1868 {
1869     if (!context->getExtensions().vertexArrayObjectOES)
1870     {
1871         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1872         return false;
1873     }
1874 
1875     return ValidateBindVertexArrayBase(context, array);
1876 }
1877 
ValidateDeleteVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)1878 bool ValidateDeleteVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
1879 {
1880     if (!context->getExtensions().vertexArrayObjectOES)
1881     {
1882         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1883         return false;
1884     }
1885 
1886     return ValidateGenOrDelete(context, n);
1887 }
1888 
ValidateGenVertexArraysOES(const Context * context,GLsizei n,const VertexArrayID * arrays)1889 bool ValidateGenVertexArraysOES(const Context *context, GLsizei n, const VertexArrayID *arrays)
1890 {
1891     if (!context->getExtensions().vertexArrayObjectOES)
1892     {
1893         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1894         return false;
1895     }
1896 
1897     return ValidateGenOrDelete(context, n);
1898 }
1899 
ValidateIsVertexArrayOES(const Context * context,VertexArrayID array)1900 bool ValidateIsVertexArrayOES(const Context *context, VertexArrayID array)
1901 {
1902     if (!context->getExtensions().vertexArrayObjectOES)
1903     {
1904         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1905         return false;
1906     }
1907 
1908     return true;
1909 }
1910 
ValidateProgramBinaryOES(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)1911 bool ValidateProgramBinaryOES(const Context *context,
1912                               ShaderProgramID program,
1913                               GLenum binaryFormat,
1914                               const void *binary,
1915                               GLint length)
1916 {
1917     if (!context->getExtensions().getProgramBinaryOES)
1918     {
1919         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1920         return false;
1921     }
1922 
1923     return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1924 }
1925 
ValidateGetProgramBinaryOES(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)1926 bool ValidateGetProgramBinaryOES(const Context *context,
1927                                  ShaderProgramID program,
1928                                  GLsizei bufSize,
1929                                  const GLsizei *length,
1930                                  const GLenum *binaryFormat,
1931                                  const void *binary)
1932 {
1933     if (!context->getExtensions().getProgramBinaryOES)
1934     {
1935         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1936         return false;
1937     }
1938 
1939     return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1940 }
1941 
ValidDebugSource(GLenum source,bool mustBeThirdPartyOrApplication)1942 static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
1943 {
1944     switch (source)
1945     {
1946         case GL_DEBUG_SOURCE_API:
1947         case GL_DEBUG_SOURCE_SHADER_COMPILER:
1948         case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1949         case GL_DEBUG_SOURCE_OTHER:
1950             // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
1951             return !mustBeThirdPartyOrApplication;
1952 
1953         case GL_DEBUG_SOURCE_THIRD_PARTY:
1954         case GL_DEBUG_SOURCE_APPLICATION:
1955             return true;
1956 
1957         default:
1958             return false;
1959     }
1960 }
1961 
ValidDebugType(GLenum type)1962 static bool ValidDebugType(GLenum type)
1963 {
1964     switch (type)
1965     {
1966         case GL_DEBUG_TYPE_ERROR:
1967         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1968         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1969         case GL_DEBUG_TYPE_PERFORMANCE:
1970         case GL_DEBUG_TYPE_PORTABILITY:
1971         case GL_DEBUG_TYPE_OTHER:
1972         case GL_DEBUG_TYPE_MARKER:
1973         case GL_DEBUG_TYPE_PUSH_GROUP:
1974         case GL_DEBUG_TYPE_POP_GROUP:
1975             return true;
1976 
1977         default:
1978             return false;
1979     }
1980 }
1981 
ValidDebugSeverity(GLenum severity)1982 static bool ValidDebugSeverity(GLenum severity)
1983 {
1984     switch (severity)
1985     {
1986         case GL_DEBUG_SEVERITY_HIGH:
1987         case GL_DEBUG_SEVERITY_MEDIUM:
1988         case GL_DEBUG_SEVERITY_LOW:
1989         case GL_DEBUG_SEVERITY_NOTIFICATION:
1990             return true;
1991 
1992         default:
1993             return false;
1994     }
1995 }
1996 
ValidateDebugMessageControlKHR(const Context * context,GLenum source,GLenum type,GLenum severity,GLsizei count,const GLuint * ids,GLboolean enabled)1997 bool ValidateDebugMessageControlKHR(const Context *context,
1998                                     GLenum source,
1999                                     GLenum type,
2000                                     GLenum severity,
2001                                     GLsizei count,
2002                                     const GLuint *ids,
2003                                     GLboolean enabled)
2004 {
2005     if (!context->getExtensions().debug)
2006     {
2007         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2008         return false;
2009     }
2010 
2011     if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
2012     {
2013         context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2014         return false;
2015     }
2016 
2017     if (!ValidDebugType(type) && type != GL_DONT_CARE)
2018     {
2019         context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2020         return false;
2021     }
2022 
2023     if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
2024     {
2025         context->validationError(GL_INVALID_ENUM, kInvalidDebugSeverity);
2026         return false;
2027     }
2028 
2029     if (count > 0)
2030     {
2031         if (source == GL_DONT_CARE || type == GL_DONT_CARE)
2032         {
2033             context->validationError(GL_INVALID_OPERATION, kInvalidDebugSourceType);
2034             return false;
2035         }
2036 
2037         if (severity != GL_DONT_CARE)
2038         {
2039             context->validationError(GL_INVALID_OPERATION, kInvalidDebugSeverity);
2040             return false;
2041         }
2042     }
2043 
2044     return true;
2045 }
2046 
ValidateDebugMessageInsertKHR(const Context * context,GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * buf)2047 bool ValidateDebugMessageInsertKHR(const Context *context,
2048                                    GLenum source,
2049                                    GLenum type,
2050                                    GLuint id,
2051                                    GLenum severity,
2052                                    GLsizei length,
2053                                    const GLchar *buf)
2054 {
2055     if (!context->getExtensions().debug)
2056     {
2057         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2058         return false;
2059     }
2060 
2061     if (!context->getState().getDebug().isOutputEnabled())
2062     {
2063         // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
2064         // not generate an error.
2065         return false;
2066     }
2067 
2068     if (!ValidDebugSeverity(severity))
2069     {
2070         context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2071         return false;
2072     }
2073 
2074     if (!ValidDebugType(type))
2075     {
2076         context->validationError(GL_INVALID_ENUM, kInvalidDebugType);
2077         return false;
2078     }
2079 
2080     if (!ValidDebugSource(source, true))
2081     {
2082         context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2083         return false;
2084     }
2085 
2086     size_t messageLength = (length < 0) ? strlen(buf) : length;
2087     if (messageLength > context->getExtensions().maxDebugMessageLength)
2088     {
2089         context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2090         return false;
2091     }
2092 
2093     return true;
2094 }
2095 
ValidateDebugMessageCallbackKHR(const Context * context,GLDEBUGPROCKHR callback,const void * userParam)2096 bool ValidateDebugMessageCallbackKHR(const Context *context,
2097                                      GLDEBUGPROCKHR callback,
2098                                      const void *userParam)
2099 {
2100     if (!context->getExtensions().debug)
2101     {
2102         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2103         return false;
2104     }
2105 
2106     return true;
2107 }
2108 
ValidateGetDebugMessageLogKHR(const Context * context,GLuint count,GLsizei bufSize,const GLenum * sources,const GLenum * types,const GLuint * ids,const GLenum * severities,const GLsizei * lengths,const GLchar * messageLog)2109 bool ValidateGetDebugMessageLogKHR(const Context *context,
2110                                    GLuint count,
2111                                    GLsizei bufSize,
2112                                    const GLenum *sources,
2113                                    const GLenum *types,
2114                                    const GLuint *ids,
2115                                    const GLenum *severities,
2116                                    const GLsizei *lengths,
2117                                    const GLchar *messageLog)
2118 {
2119     if (!context->getExtensions().debug)
2120     {
2121         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2122         return false;
2123     }
2124 
2125     if (bufSize < 0 && messageLog != nullptr)
2126     {
2127         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2128         return false;
2129     }
2130 
2131     return true;
2132 }
2133 
ValidatePushDebugGroupKHR(const Context * context,GLenum source,GLuint id,GLsizei length,const GLchar * message)2134 bool ValidatePushDebugGroupKHR(const Context *context,
2135                                GLenum source,
2136                                GLuint id,
2137                                GLsizei length,
2138                                const GLchar *message)
2139 {
2140     if (!context->getExtensions().debug)
2141     {
2142         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2143         return false;
2144     }
2145 
2146     if (!ValidDebugSource(source, true))
2147     {
2148         context->validationError(GL_INVALID_ENUM, kInvalidDebugSource);
2149         return false;
2150     }
2151 
2152     size_t messageLength = (length < 0) ? strlen(message) : length;
2153     if (messageLength > context->getExtensions().maxDebugMessageLength)
2154     {
2155         context->validationError(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
2156         return false;
2157     }
2158 
2159     size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2160     if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
2161     {
2162         context->validationError(GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
2163         return false;
2164     }
2165 
2166     return true;
2167 }
2168 
ValidatePopDebugGroupKHR(const Context * context)2169 bool ValidatePopDebugGroupKHR(const Context *context)
2170 {
2171     if (!context->getExtensions().debug)
2172     {
2173         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2174         return false;
2175     }
2176 
2177     size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
2178     if (currentStackSize <= 1)
2179     {
2180         context->validationError(GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
2181         return false;
2182     }
2183 
2184     return true;
2185 }
2186 
ValidateObjectIdentifierAndName(const Context * context,GLenum identifier,GLuint name)2187 static bool ValidateObjectIdentifierAndName(const Context *context, GLenum identifier, GLuint name)
2188 {
2189     switch (identifier)
2190     {
2191         case GL_BUFFER:
2192             if (context->getBuffer({name}) == nullptr)
2193             {
2194                 context->validationError(GL_INVALID_VALUE, kInvalidBufferName);
2195                 return false;
2196             }
2197             return true;
2198 
2199         case GL_SHADER:
2200             if (context->getShader({name}) == nullptr)
2201             {
2202                 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
2203                 return false;
2204             }
2205             return true;
2206 
2207         case GL_PROGRAM:
2208             if (context->getProgramNoResolveLink({name}) == nullptr)
2209             {
2210                 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
2211                 return false;
2212             }
2213             return true;
2214 
2215         case GL_VERTEX_ARRAY:
2216             if (context->getVertexArray({name}) == nullptr)
2217             {
2218                 context->validationError(GL_INVALID_VALUE, kInvalidVertexArrayName);
2219                 return false;
2220             }
2221             return true;
2222 
2223         case GL_QUERY:
2224             if (context->getQuery({name}) == nullptr)
2225             {
2226                 context->validationError(GL_INVALID_VALUE, kInvalidQueryName);
2227                 return false;
2228             }
2229             return true;
2230 
2231         case GL_TRANSFORM_FEEDBACK:
2232             if (context->getTransformFeedback({name}) == nullptr)
2233             {
2234                 context->validationError(GL_INVALID_VALUE, kInvalidTransformFeedbackName);
2235                 return false;
2236             }
2237             return true;
2238 
2239         case GL_SAMPLER:
2240             if (context->getSampler({name}) == nullptr)
2241             {
2242                 context->validationError(GL_INVALID_VALUE, kInvalidSamplerName);
2243                 return false;
2244             }
2245             return true;
2246 
2247         case GL_TEXTURE:
2248             if (context->getTexture({name}) == nullptr)
2249             {
2250                 context->validationError(GL_INVALID_VALUE, kInvalidTextureName);
2251                 return false;
2252             }
2253             return true;
2254 
2255         case GL_RENDERBUFFER:
2256             if (!context->isRenderbuffer({name}))
2257             {
2258                 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferName);
2259                 return false;
2260             }
2261             return true;
2262 
2263         case GL_FRAMEBUFFER:
2264             if (context->getFramebuffer({name}) == nullptr)
2265             {
2266                 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferName);
2267                 return false;
2268             }
2269             return true;
2270 
2271         case GL_PROGRAM_PIPELINE:
2272             if (context->getProgramPipeline({name}) == nullptr)
2273             {
2274                 context->validationError(GL_INVALID_VALUE, kInvalidProgramPipelineName);
2275                 return false;
2276             }
2277             return true;
2278 
2279         default:
2280             context->validationError(GL_INVALID_ENUM, kInvalidIndentifier);
2281             return false;
2282     }
2283 }
2284 
ValidateLabelLength(const Context * context,GLsizei length,const GLchar * label)2285 static bool ValidateLabelLength(const Context *context, GLsizei length, const GLchar *label)
2286 {
2287     size_t labelLength = 0;
2288 
2289     if (length < 0)
2290     {
2291         if (label != nullptr)
2292         {
2293             labelLength = strlen(label);
2294         }
2295     }
2296     else
2297     {
2298         labelLength = static_cast<size_t>(length);
2299     }
2300 
2301     if (labelLength > context->getExtensions().maxLabelLength)
2302     {
2303         context->validationError(GL_INVALID_VALUE, kExceedsMaxLabelLength);
2304         return false;
2305     }
2306 
2307     return true;
2308 }
2309 
ValidateObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei length,const GLchar * label)2310 bool ValidateObjectLabelKHR(const Context *context,
2311                             GLenum identifier,
2312                             GLuint name,
2313                             GLsizei length,
2314                             const GLchar *label)
2315 {
2316     if (!context->getExtensions().debug)
2317     {
2318         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2319         return false;
2320     }
2321 
2322     if (!ValidateObjectIdentifierAndName(context, identifier, name))
2323     {
2324         return false;
2325     }
2326 
2327     if (!ValidateLabelLength(context, length, label))
2328     {
2329         return false;
2330     }
2331 
2332     return true;
2333 }
2334 
ValidateGetObjectLabelKHR(const Context * context,GLenum identifier,GLuint name,GLsizei bufSize,const GLsizei * length,const GLchar * label)2335 bool ValidateGetObjectLabelKHR(const Context *context,
2336                                GLenum identifier,
2337                                GLuint name,
2338                                GLsizei bufSize,
2339                                const GLsizei *length,
2340                                const GLchar *label)
2341 {
2342     if (!context->getExtensions().debug)
2343     {
2344         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2345         return false;
2346     }
2347 
2348     if (bufSize < 0)
2349     {
2350         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2351         return false;
2352     }
2353 
2354     if (!ValidateObjectIdentifierAndName(context, identifier, name))
2355     {
2356         return false;
2357     }
2358 
2359     return true;
2360 }
2361 
ValidateObjectPtrName(const Context * context,const void * ptr)2362 static bool ValidateObjectPtrName(const Context *context, const void *ptr)
2363 {
2364     if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
2365     {
2366         context->validationError(GL_INVALID_VALUE, kInvalidSyncPointer);
2367         return false;
2368     }
2369 
2370     return true;
2371 }
2372 
ValidateObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei length,const GLchar * label)2373 bool ValidateObjectPtrLabelKHR(const Context *context,
2374                                const void *ptr,
2375                                GLsizei length,
2376                                const GLchar *label)
2377 {
2378     if (!context->getExtensions().debug)
2379     {
2380         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2381         return false;
2382     }
2383 
2384     if (!ValidateObjectPtrName(context, ptr))
2385     {
2386         return false;
2387     }
2388 
2389     if (!ValidateLabelLength(context, length, label))
2390     {
2391         return false;
2392     }
2393 
2394     return true;
2395 }
2396 
ValidateGetObjectPtrLabelKHR(const Context * context,const void * ptr,GLsizei bufSize,const GLsizei * length,const GLchar * label)2397 bool ValidateGetObjectPtrLabelKHR(const Context *context,
2398                                   const void *ptr,
2399                                   GLsizei bufSize,
2400                                   const GLsizei *length,
2401                                   const GLchar *label)
2402 {
2403     if (!context->getExtensions().debug)
2404     {
2405         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2406         return false;
2407     }
2408 
2409     if (bufSize < 0)
2410     {
2411         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
2412         return false;
2413     }
2414 
2415     if (!ValidateObjectPtrName(context, ptr))
2416     {
2417         return false;
2418     }
2419 
2420     return true;
2421 }
2422 
ValidateGetPointervKHR(const Context * context,GLenum pname,void * const * params)2423 bool ValidateGetPointervKHR(const Context *context, GLenum pname, void *const *params)
2424 {
2425     if (!context->getExtensions().debug)
2426     {
2427         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2428         return false;
2429     }
2430 
2431     // TODO: represent this in Context::getQueryParameterInfo.
2432     switch (pname)
2433     {
2434         case GL_DEBUG_CALLBACK_FUNCTION:
2435         case GL_DEBUG_CALLBACK_USER_PARAM:
2436             break;
2437 
2438         default:
2439             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2440             return false;
2441     }
2442 
2443     return true;
2444 }
2445 
ValidateGetPointervRobustANGLERobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)2446 bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
2447                                                GLenum pname,
2448                                                GLsizei bufSize,
2449                                                const GLsizei *length,
2450                                                void *const *params)
2451 {
2452     UNIMPLEMENTED();
2453     return false;
2454 }
2455 
ValidateBlitFramebufferANGLE(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2456 bool ValidateBlitFramebufferANGLE(const Context *context,
2457                                   GLint srcX0,
2458                                   GLint srcY0,
2459                                   GLint srcX1,
2460                                   GLint srcY1,
2461                                   GLint dstX0,
2462                                   GLint dstY0,
2463                                   GLint dstX1,
2464                                   GLint dstY1,
2465                                   GLbitfield mask,
2466                                   GLenum filter)
2467 {
2468     if (!context->getExtensions().framebufferBlitANGLE)
2469     {
2470         context->validationError(GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
2471         return false;
2472     }
2473 
2474     if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
2475     {
2476         // TODO(jmadill): Determine if this should be available on other implementations.
2477         context->validationError(GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
2478         return false;
2479     }
2480 
2481     if (filter == GL_LINEAR)
2482     {
2483         context->validationError(GL_INVALID_ENUM, kBlitExtensionLinear);
2484         return false;
2485     }
2486 
2487     Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
2488     Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
2489 
2490     if (mask & GL_COLOR_BUFFER_BIT)
2491     {
2492         const FramebufferAttachment *readColorAttachment =
2493             readFramebuffer->getReadColorAttachment();
2494         const FramebufferAttachment *drawColorAttachment =
2495             drawFramebuffer->getFirstColorAttachment();
2496 
2497         if (readColorAttachment && drawColorAttachment)
2498         {
2499             if (!(readColorAttachment->type() == GL_TEXTURE &&
2500                   (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
2501                    readColorAttachment->getTextureImageIndex().getType() ==
2502                        TextureType::Rectangle)) &&
2503                 readColorAttachment->type() != GL_RENDERBUFFER &&
2504                 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
2505             {
2506                 context->validationError(GL_INVALID_OPERATION,
2507                                          kBlitExtensionFromInvalidAttachmentType);
2508                 return false;
2509             }
2510 
2511             for (size_t drawbufferIdx = 0;
2512                  drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
2513             {
2514                 const FramebufferAttachment *attachment =
2515                     drawFramebuffer->getDrawBuffer(drawbufferIdx);
2516                 if (attachment)
2517                 {
2518                     if (!(attachment->type() == GL_TEXTURE &&
2519                           (attachment->getTextureImageIndex().getType() == TextureType::_2D ||
2520                            attachment->getTextureImageIndex().getType() ==
2521                                TextureType::Rectangle)) &&
2522                         attachment->type() != GL_RENDERBUFFER &&
2523                         attachment->type() != GL_FRAMEBUFFER_DEFAULT)
2524                     {
2525                         context->validationError(GL_INVALID_OPERATION,
2526                                                  kBlitExtensionToInvalidAttachmentType);
2527                         return false;
2528                     }
2529 
2530                     // Return an error if the destination formats do not match
2531                     if (!Format::EquivalentForBlit(attachment->getFormat(),
2532                                                    readColorAttachment->getFormat()))
2533                     {
2534                         context->validationError(GL_INVALID_OPERATION,
2535                                                  kBlitExtensionFormatMismatch);
2536                         return false;
2537                     }
2538                 }
2539             }
2540 
2541             GLint samples = readFramebuffer->getSamples(context);
2542             if (samples != 0 &&
2543                 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
2544                               srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
2545             {
2546                 context->validationError(GL_INVALID_OPERATION,
2547                                          kBlitExtensionMultisampledWholeBufferBlit);
2548                 return false;
2549             }
2550         }
2551     }
2552 
2553     GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2554     GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2555     for (size_t i = 0; i < 2; i++)
2556     {
2557         if (mask & masks[i])
2558         {
2559             const FramebufferAttachment *readBuffer =
2560                 readFramebuffer->getAttachment(context, attachments[i]);
2561             const FramebufferAttachment *drawBuffer =
2562                 drawFramebuffer->getAttachment(context, attachments[i]);
2563 
2564             if (readBuffer && drawBuffer)
2565             {
2566                 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
2567                                   dstX0, dstY0, dstX1, dstY1))
2568                 {
2569                     // only whole-buffer copies are permitted
2570                     context->validationError(GL_INVALID_OPERATION,
2571                                              kBlitExtensionDepthStencilWholeBufferBlit);
2572                     return false;
2573                 }
2574 
2575                 if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0)
2576                 {
2577                     context->validationError(GL_INVALID_OPERATION,
2578                                              kBlitExtensionMultisampledDepthOrStencil);
2579                     return false;
2580                 }
2581             }
2582         }
2583     }
2584 
2585     return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2586                                              dstX1, dstY1, mask, filter);
2587 }
2588 
ValidateBlitFramebufferNV(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2589 bool ValidateBlitFramebufferNV(const Context *context,
2590                                GLint srcX0,
2591                                GLint srcY0,
2592                                GLint srcX1,
2593                                GLint srcY1,
2594                                GLint dstX0,
2595                                GLint dstY0,
2596                                GLint dstX1,
2597                                GLint dstY1,
2598                                GLbitfield mask,
2599                                GLenum filter)
2600 {
2601     if (!context->getExtensions().framebufferBlitANGLE)
2602     {
2603         context->validationError(GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
2604         return false;
2605     }
2606 
2607     return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
2608                                              dstX1, dstY1, mask, filter);
2609 }
2610 
ValidateClear(const Context * context,GLbitfield mask)2611 bool ValidateClear(const Context *context, GLbitfield mask)
2612 {
2613     Framebuffer *fbo             = context->getState().getDrawFramebuffer();
2614     const Extensions &extensions = context->getExtensions();
2615 
2616     if (!ValidateFramebufferComplete(context, fbo))
2617     {
2618         return false;
2619     }
2620 
2621     if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
2622     {
2623         context->validationError(GL_INVALID_VALUE, kInvalidClearMask);
2624         return false;
2625     }
2626 
2627     if (extensions.webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
2628     {
2629         constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2630                                                   GL_SIGNED_NORMALIZED};
2631 
2632         for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
2633              drawBufferIdx++)
2634         {
2635             if (!ValidateWebGLFramebufferAttachmentClearType(
2636                     context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
2637             {
2638                 return false;
2639             }
2640         }
2641     }
2642 
2643     if ((extensions.multiview || extensions.multiview2) && extensions.disjointTimerQuery)
2644     {
2645         const State &state       = context->getState();
2646         Framebuffer *framebuffer = state.getDrawFramebuffer();
2647         if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
2648         {
2649             context->validationError(GL_INVALID_OPERATION, kMultiviewTimerQuery);
2650             return false;
2651         }
2652     }
2653 
2654     return true;
2655 }
2656 
ValidateDrawBuffersEXT(const Context * context,GLsizei n,const GLenum * bufs)2657 bool ValidateDrawBuffersEXT(const Context *context, GLsizei n, const GLenum *bufs)
2658 {
2659     if (!context->getExtensions().drawBuffers)
2660     {
2661         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2662         return false;
2663     }
2664 
2665     return ValidateDrawBuffersBase(context, n, bufs);
2666 }
2667 
ValidateTexImage2D(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)2668 bool ValidateTexImage2D(const Context *context,
2669                         TextureTarget target,
2670                         GLint level,
2671                         GLint internalformat,
2672                         GLsizei width,
2673                         GLsizei height,
2674                         GLint border,
2675                         GLenum format,
2676                         GLenum type,
2677                         const void *pixels)
2678 {
2679     if (context->getClientMajorVersion() < 3)
2680     {
2681         return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2682                                              0, 0, width, height, border, format, type, -1, pixels);
2683     }
2684 
2685     ASSERT(context->getClientMajorVersion() >= 3);
2686     return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2687                                            0, 0, width, height, 1, border, format, type, -1,
2688                                            pixels);
2689 }
2690 
ValidateTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2691 bool ValidateTexImage2DRobustANGLE(const Context *context,
2692                                    TextureTarget target,
2693                                    GLint level,
2694                                    GLint internalformat,
2695                                    GLsizei width,
2696                                    GLsizei height,
2697                                    GLint border,
2698                                    GLenum format,
2699                                    GLenum type,
2700                                    GLsizei bufSize,
2701                                    const void *pixels)
2702 {
2703     if (!ValidateRobustEntryPoint(context, bufSize))
2704     {
2705         return false;
2706     }
2707 
2708     if (context->getClientMajorVersion() < 3)
2709     {
2710         return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
2711                                              0, 0, width, height, border, format, type, bufSize,
2712                                              pixels);
2713     }
2714 
2715     ASSERT(context->getClientMajorVersion() >= 3);
2716     return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
2717                                            0, 0, width, height, 1, border, format, type, bufSize,
2718                                            pixels);
2719 }
2720 
ValidateTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)2721 bool ValidateTexSubImage2D(const Context *context,
2722                            TextureTarget target,
2723                            GLint level,
2724                            GLint xoffset,
2725                            GLint yoffset,
2726                            GLsizei width,
2727                            GLsizei height,
2728                            GLenum format,
2729                            GLenum type,
2730                            const void *pixels)
2731 {
2732 
2733     if (context->getClientMajorVersion() < 3)
2734     {
2735         return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2736                                              yoffset, width, height, 0, format, type, -1, pixels);
2737     }
2738 
2739     ASSERT(context->getClientMajorVersion() >= 3);
2740     return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2741                                            yoffset, 0, width, height, 1, 0, format, type, -1,
2742                                            pixels);
2743 }
2744 
ValidateTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2745 bool ValidateTexSubImage2DRobustANGLE(const Context *context,
2746                                       TextureTarget target,
2747                                       GLint level,
2748                                       GLint xoffset,
2749                                       GLint yoffset,
2750                                       GLsizei width,
2751                                       GLsizei height,
2752                                       GLenum format,
2753                                       GLenum type,
2754                                       GLsizei bufSize,
2755                                       const void *pixels)
2756 {
2757     if (!ValidateRobustEntryPoint(context, bufSize))
2758     {
2759         return false;
2760     }
2761 
2762     if (context->getClientMajorVersion() < 3)
2763     {
2764         return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
2765                                              yoffset, width, height, 0, format, type, bufSize,
2766                                              pixels);
2767     }
2768 
2769     ASSERT(context->getClientMajorVersion() >= 3);
2770     return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
2771                                            yoffset, 0, width, height, 1, 0, format, type, bufSize,
2772                                            pixels);
2773 }
2774 
ValidateTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2775 bool ValidateTexSubImage3DOES(const Context *context,
2776                               TextureTarget target,
2777                               GLint level,
2778                               GLint xoffset,
2779                               GLint yoffset,
2780                               GLint zoffset,
2781                               GLsizei width,
2782                               GLsizei height,
2783                               GLsizei depth,
2784                               GLenum format,
2785                               GLenum type,
2786                               const void *pixels)
2787 {
2788     return ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
2789                                  depth, format, type, pixels);
2790 }
2791 
ValidateCompressedTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const void * data)2792 bool ValidateCompressedTexImage2D(const Context *context,
2793                                   TextureTarget target,
2794                                   GLint level,
2795                                   GLenum internalformat,
2796                                   GLsizei width,
2797                                   GLsizei height,
2798                                   GLint border,
2799                                   GLsizei imageSize,
2800                                   const void *data)
2801 {
2802     if (context->getClientMajorVersion() < 3)
2803     {
2804         if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
2805                                            0, width, height, border, GL_NONE, GL_NONE, -1, data))
2806         {
2807             return false;
2808         }
2809     }
2810     else
2811     {
2812         ASSERT(context->getClientMajorVersion() >= 3);
2813         if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
2814                                              0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
2815                                              data))
2816         {
2817             return false;
2818         }
2819     }
2820 
2821     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
2822 
2823     GLuint blockSize = 0;
2824     if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
2825     {
2826         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
2827         return false;
2828     }
2829 
2830     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2831     {
2832         context->validationError(GL_INVALID_VALUE, kCompressedTextureDimensionsMustMatchData);
2833         return false;
2834     }
2835 
2836     if (target == TextureTarget::Rectangle)
2837     {
2838         context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
2839         return false;
2840     }
2841 
2842     return true;
2843 }
2844 
ValidateCompressedTexImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)2845 bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
2846                                              TextureTarget target,
2847                                              GLint level,
2848                                              GLenum internalformat,
2849                                              GLsizei width,
2850                                              GLsizei height,
2851                                              GLint border,
2852                                              GLsizei imageSize,
2853                                              GLsizei dataSize,
2854                                              const void *data)
2855 {
2856     if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2857     {
2858         return false;
2859     }
2860 
2861     return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
2862                                         border, imageSize, data);
2863 }
2864 
ValidateCompressedTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)2865 bool ValidateCompressedTexImage3DOES(const Context *context,
2866                                      TextureTarget target,
2867                                      GLint level,
2868                                      GLenum internalformat,
2869                                      GLsizei width,
2870                                      GLsizei height,
2871                                      GLsizei depth,
2872                                      GLint border,
2873                                      GLsizei imageSize,
2874                                      const void *data)
2875 {
2876     return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
2877                                         depth, border, imageSize, data);
2878 }
2879 
ValidateCompressedTexSubImage2DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2880 bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
2881                                                 TextureTarget target,
2882                                                 GLint level,
2883                                                 GLint xoffset,
2884                                                 GLint yoffset,
2885                                                 GLsizei width,
2886                                                 GLsizei height,
2887                                                 GLenum format,
2888                                                 GLsizei imageSize,
2889                                                 GLsizei dataSize,
2890                                                 const void *data)
2891 {
2892     if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2893     {
2894         return false;
2895     }
2896 
2897     return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
2898                                            format, imageSize, data);
2899 }
2900 
ValidateCompressedTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const void * data)2901 bool ValidateCompressedTexSubImage2D(const Context *context,
2902                                      TextureTarget target,
2903                                      GLint level,
2904                                      GLint xoffset,
2905                                      GLint yoffset,
2906                                      GLsizei width,
2907                                      GLsizei height,
2908                                      GLenum format,
2909                                      GLsizei imageSize,
2910                                      const void *data)
2911 {
2912     if (context->getClientMajorVersion() < 3)
2913     {
2914         if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
2915                                            yoffset, width, height, 0, format, GL_NONE, -1, data))
2916         {
2917             return false;
2918         }
2919     }
2920     else
2921     {
2922         ASSERT(context->getClientMajorVersion() >= 3);
2923         if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
2924                                              yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
2925                                              data))
2926         {
2927             return false;
2928         }
2929     }
2930 
2931     const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2932     GLuint blockSize                 = 0;
2933     if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
2934     {
2935         context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
2936         return false;
2937     }
2938 
2939     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2940     {
2941         context->validationError(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2942         return false;
2943     }
2944 
2945     return true;
2946 }
2947 
ValidateCompressedTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)2948 bool ValidateCompressedTexSubImage3DOES(const Context *context,
2949                                         TextureTarget target,
2950                                         GLint level,
2951                                         GLint xoffset,
2952                                         GLint yoffset,
2953                                         GLint zoffset,
2954                                         GLsizei width,
2955                                         GLsizei height,
2956                                         GLsizei depth,
2957                                         GLenum format,
2958                                         GLsizei imageSize,
2959                                         const void *data)
2960 {
2961     return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2962                                            height, depth, format, imageSize, data);
2963 }
2964 
ValidateGetBufferPointervOES(const Context * context,BufferBinding target,GLenum pname,void * const * params)2965 bool ValidateGetBufferPointervOES(const Context *context,
2966                                   BufferBinding target,
2967                                   GLenum pname,
2968                                   void *const *params)
2969 {
2970     if (!context->getExtensions().mapBufferOES)
2971     {
2972         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2973         return false;
2974     }
2975 
2976     return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2977 }
2978 
ValidateMapBufferOES(const Context * context,BufferBinding target,GLenum access)2979 bool ValidateMapBufferOES(const Context *context, BufferBinding target, GLenum access)
2980 {
2981     if (!context->getExtensions().mapBufferOES)
2982     {
2983         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2984         return false;
2985     }
2986 
2987     if (!context->isValidBufferBinding(target))
2988     {
2989         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
2990         return false;
2991     }
2992 
2993     Buffer *buffer = context->getState().getTargetBuffer(target);
2994 
2995     if (buffer == nullptr)
2996     {
2997         context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
2998         return false;
2999     }
3000 
3001     if (access != GL_WRITE_ONLY_OES)
3002     {
3003         context->validationError(GL_INVALID_ENUM, kInvalidAccessBits);
3004         return false;
3005     }
3006 
3007     // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage
3008     // and GL_OES_mapbuffer extension, allow it as long as the access type of glMapBufferOES
3009     // is compatible with the buffer's usage flags specified during glBufferStorageEXT
3010     if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0)
3011     {
3012         context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3013         return false;
3014     }
3015 
3016     if (buffer->isMapped())
3017     {
3018         context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
3019         return false;
3020     }
3021 
3022     return ValidateMapBufferBase(context, target);
3023 }
3024 
ValidateUnmapBufferOES(const Context * context,BufferBinding target)3025 bool ValidateUnmapBufferOES(const Context *context, BufferBinding target)
3026 {
3027     if (!context->getExtensions().mapBufferOES)
3028     {
3029         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3030         return false;
3031     }
3032 
3033     return ValidateUnmapBufferBase(context, target);
3034 }
3035 
ValidateMapBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3036 bool ValidateMapBufferRangeEXT(const Context *context,
3037                                BufferBinding target,
3038                                GLintptr offset,
3039                                GLsizeiptr length,
3040                                GLbitfield access)
3041 {
3042     if (!context->getExtensions().mapBufferRange)
3043     {
3044         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3045         return false;
3046     }
3047 
3048     return ValidateMapBufferRangeBase(context, target, offset, length, access);
3049 }
3050 
ValidateMapBufferBase(const Context * context,BufferBinding target)3051 bool ValidateMapBufferBase(const Context *context, BufferBinding target)
3052 {
3053     Buffer *buffer = context->getState().getTargetBuffer(target);
3054     ASSERT(buffer != nullptr);
3055 
3056     // Check if this buffer is currently being used as a transform feedback output buffer
3057     if (context->getState().isTransformFeedbackActive())
3058     {
3059         TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3060         for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
3061         {
3062             const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
3063             if (transformFeedbackBuffer.get() == buffer)
3064             {
3065                 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3066                 return false;
3067             }
3068         }
3069     }
3070 
3071     if (context->getExtensions().webglCompatibility &&
3072         buffer->isBoundForTransformFeedbackAndOtherUse())
3073     {
3074         context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3075         return false;
3076     }
3077 
3078     return true;
3079 }
3080 
ValidateFlushMappedBufferRangeEXT(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)3081 bool ValidateFlushMappedBufferRangeEXT(const Context *context,
3082                                        BufferBinding target,
3083                                        GLintptr offset,
3084                                        GLsizeiptr length)
3085 {
3086     if (!context->getExtensions().mapBufferRange)
3087     {
3088         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3089         return false;
3090     }
3091 
3092     return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
3093 }
3094 
ValidateBindUniformLocationCHROMIUM(const Context * context,ShaderProgramID program,UniformLocation location,const GLchar * name)3095 bool ValidateBindUniformLocationCHROMIUM(const Context *context,
3096                                          ShaderProgramID program,
3097                                          UniformLocation location,
3098                                          const GLchar *name)
3099 {
3100     if (!context->getExtensions().bindUniformLocation)
3101     {
3102         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3103         return false;
3104     }
3105 
3106     Program *programObject = GetValidProgram(context, program);
3107     if (!programObject)
3108     {
3109         return false;
3110     }
3111 
3112     if (location.value < 0)
3113     {
3114         context->validationError(GL_INVALID_VALUE, kNegativeLocation);
3115         return false;
3116     }
3117 
3118     const Caps &caps = context->getCaps();
3119     if (static_cast<long>(location.value) >=
3120         (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
3121     {
3122         context->validationError(GL_INVALID_VALUE, kInvalidBindUniformLocation);
3123         return false;
3124     }
3125 
3126     // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
3127     // shader-related entry points
3128     if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
3129     {
3130         context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
3131         return false;
3132     }
3133 
3134     if (strncmp(name, "gl_", 3) == 0)
3135     {
3136         context->validationError(GL_INVALID_VALUE, kNameBeginsWithGL);
3137         return false;
3138     }
3139 
3140     return true;
3141 }
3142 
ValidateCoverageModulationCHROMIUM(const Context * context,GLenum components)3143 bool ValidateCoverageModulationCHROMIUM(const Context *context, GLenum components)
3144 {
3145     if (!context->getExtensions().framebufferMixedSamples)
3146     {
3147         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3148         return false;
3149     }
3150     switch (components)
3151     {
3152         case GL_RGB:
3153         case GL_RGBA:
3154         case GL_ALPHA:
3155         case GL_NONE:
3156             break;
3157         default:
3158             context->validationError(GL_INVALID_ENUM, kInvalidCoverageComponents);
3159             return false;
3160     }
3161 
3162     return true;
3163 }
3164 
ValidateCopyTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3165 bool ValidateCopyTextureCHROMIUM(const Context *context,
3166                                  TextureID sourceId,
3167                                  GLint sourceLevel,
3168                                  TextureTarget destTarget,
3169                                  TextureID destId,
3170                                  GLint destLevel,
3171                                  GLint internalFormat,
3172                                  GLenum destType,
3173                                  GLboolean unpackFlipY,
3174                                  GLboolean unpackPremultiplyAlpha,
3175                                  GLboolean unpackUnmultiplyAlpha)
3176 {
3177     if (!context->getExtensions().copyTexture)
3178     {
3179         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3180         return false;
3181     }
3182 
3183     const Texture *source = context->getTexture(sourceId);
3184     if (source == nullptr)
3185     {
3186         context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3187         return false;
3188     }
3189 
3190     if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3191     {
3192         context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3193         return false;
3194     }
3195 
3196     TextureType sourceType = source->getType();
3197     ASSERT(sourceType != TextureType::CubeMap);
3198     TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3199 
3200     if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3201     {
3202         context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3203         return false;
3204     }
3205 
3206     GLsizei sourceWidth  = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
3207     GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
3208     if (sourceWidth == 0 || sourceHeight == 0)
3209     {
3210         context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3211         return false;
3212     }
3213 
3214     const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
3215     if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
3216     {
3217         context->validationError(GL_INVALID_OPERATION, kInvalidSourceTextureInternalFormat);
3218         return false;
3219     }
3220 
3221     if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3222     {
3223         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3224         return false;
3225     }
3226 
3227     const Texture *dest = context->getTexture(destId);
3228     if (dest == nullptr)
3229     {
3230         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3231         return false;
3232     }
3233 
3234     if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3235     {
3236         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3237         return false;
3238     }
3239 
3240     if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, sourceWidth,
3241                                             sourceHeight, false))
3242     {
3243         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3244         return false;
3245     }
3246 
3247     if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
3248     {
3249         return false;
3250     }
3251 
3252     if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
3253     {
3254         context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
3255         return false;
3256     }
3257 
3258     if (dest->getImmutableFormat())
3259     {
3260         context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
3261         return false;
3262     }
3263 
3264     return true;
3265 }
3266 
ValidateCopySubTextureCHROMIUM(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)3267 bool ValidateCopySubTextureCHROMIUM(const Context *context,
3268                                     TextureID sourceId,
3269                                     GLint sourceLevel,
3270                                     TextureTarget destTarget,
3271                                     TextureID destId,
3272                                     GLint destLevel,
3273                                     GLint xoffset,
3274                                     GLint yoffset,
3275                                     GLint x,
3276                                     GLint y,
3277                                     GLsizei width,
3278                                     GLsizei height,
3279                                     GLboolean unpackFlipY,
3280                                     GLboolean unpackPremultiplyAlpha,
3281                                     GLboolean unpackUnmultiplyAlpha)
3282 {
3283     if (!context->getExtensions().copyTexture)
3284     {
3285         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3286         return false;
3287     }
3288 
3289     const Texture *source = context->getTexture(sourceId);
3290     if (source == nullptr)
3291     {
3292         context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3293         return false;
3294     }
3295 
3296     if (!IsValidCopyTextureSourceTarget(context, source->getType()))
3297     {
3298         context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3299         return false;
3300     }
3301 
3302     TextureType sourceType = source->getType();
3303     ASSERT(sourceType != TextureType::CubeMap);
3304     TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
3305 
3306     if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
3307     {
3308         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3309         return false;
3310     }
3311 
3312     if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
3313         source->getHeight(sourceTarget, sourceLevel) == 0)
3314     {
3315         context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
3316         return false;
3317     }
3318 
3319     if (x < 0 || y < 0)
3320     {
3321         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3322         return false;
3323     }
3324 
3325     if (width < 0 || height < 0)
3326     {
3327         context->validationError(GL_INVALID_VALUE, kNegativeSize);
3328         return false;
3329     }
3330 
3331     if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
3332         static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
3333     {
3334         context->validationError(GL_INVALID_VALUE, kSourceTextureTooSmall);
3335         return false;
3336     }
3337 
3338     const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
3339     if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
3340     {
3341         context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
3342         return false;
3343     }
3344 
3345     if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
3346     {
3347         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3348         return false;
3349     }
3350 
3351     const Texture *dest = context->getTexture(destId);
3352     if (dest == nullptr)
3353     {
3354         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3355         return false;
3356     }
3357 
3358     if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
3359     {
3360         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3361         return false;
3362     }
3363 
3364     if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, width, height,
3365                                             true))
3366     {
3367         context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3368         return false;
3369     }
3370 
3371     if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
3372     {
3373         context->validationError(GL_INVALID_OPERATION, kDestinationLevelNotDefined);
3374         return false;
3375     }
3376 
3377     const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
3378     if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
3379     {
3380         context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
3381         return false;
3382     }
3383 
3384     if (xoffset < 0 || yoffset < 0)
3385     {
3386         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3387         return false;
3388     }
3389 
3390     if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
3391         static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
3392     {
3393         context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
3394         return false;
3395     }
3396 
3397     return true;
3398 }
3399 
ValidateCompressedCopyTextureCHROMIUM(const Context * context,TextureID sourceId,TextureID destId)3400 bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
3401                                            TextureID sourceId,
3402                                            TextureID destId)
3403 {
3404     if (!context->getExtensions().copyCompressedTexture)
3405     {
3406         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3407         return false;
3408     }
3409 
3410     const Texture *source = context->getTexture(sourceId);
3411     if (source == nullptr)
3412     {
3413         context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
3414         return false;
3415     }
3416 
3417     if (source->getType() != TextureType::_2D)
3418     {
3419         context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureType);
3420         return false;
3421     }
3422 
3423     if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
3424         source->getHeight(TextureTarget::_2D, 0) == 0)
3425     {
3426         context->validationError(GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
3427         return false;
3428     }
3429 
3430     const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
3431     if (!sourceFormat.info->compressed)
3432     {
3433         context->validationError(GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
3434         return false;
3435     }
3436 
3437     const Texture *dest = context->getTexture(destId);
3438     if (dest == nullptr)
3439     {
3440         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
3441         return false;
3442     }
3443 
3444     if (dest->getType() != TextureType::_2D)
3445     {
3446         context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
3447         return false;
3448     }
3449 
3450     if (dest->getImmutableFormat())
3451     {
3452         context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
3453         return false;
3454     }
3455 
3456     return true;
3457 }
3458 
ValidateCreateShader(const Context * context,ShaderType type)3459 bool ValidateCreateShader(const Context *context, ShaderType type)
3460 {
3461     switch (type)
3462     {
3463         case ShaderType::Vertex:
3464         case ShaderType::Fragment:
3465             break;
3466 
3467         case ShaderType::Compute:
3468             if (context->getClientVersion() < ES_3_1)
3469             {
3470                 context->validationError(GL_INVALID_ENUM, kES31Required);
3471                 return false;
3472             }
3473             break;
3474 
3475         case ShaderType::Geometry:
3476             if (!context->getExtensions().geometryShader && context->getClientVersion() < ES_3_2)
3477             {
3478                 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3479                 return false;
3480             }
3481             break;
3482 
3483         case ShaderType::TessControl:
3484             if (!context->getExtensions().tessellationShaderEXT &&
3485                 context->getClientVersion() < ES_3_2)
3486             {
3487                 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3488                 return false;
3489             }
3490             break;
3491 
3492         case ShaderType::TessEvaluation:
3493             if (!context->getExtensions().tessellationShaderEXT &&
3494                 context->getClientVersion() < ES_3_2)
3495             {
3496                 context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3497                 return false;
3498             }
3499             break;
3500 
3501         default:
3502             context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
3503             return false;
3504     }
3505 
3506     return true;
3507 }
3508 
ValidateBufferData(const Context * context,BufferBinding target,GLsizeiptr size,const void * data,BufferUsage usage)3509 bool ValidateBufferData(const Context *context,
3510                         BufferBinding target,
3511                         GLsizeiptr size,
3512                         const void *data,
3513                         BufferUsage usage)
3514 {
3515     if (size < 0)
3516     {
3517         context->validationError(GL_INVALID_VALUE, kNegativeSize);
3518         return false;
3519     }
3520 
3521     switch (usage)
3522     {
3523         case BufferUsage::StreamDraw:
3524         case BufferUsage::StaticDraw:
3525         case BufferUsage::DynamicDraw:
3526             break;
3527 
3528         case BufferUsage::StreamRead:
3529         case BufferUsage::StaticRead:
3530         case BufferUsage::DynamicRead:
3531         case BufferUsage::StreamCopy:
3532         case BufferUsage::StaticCopy:
3533         case BufferUsage::DynamicCopy:
3534             if (context->getClientMajorVersion() < 3)
3535             {
3536                 context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
3537                 return false;
3538             }
3539             break;
3540 
3541         default:
3542             context->validationError(GL_INVALID_ENUM, kInvalidBufferUsage);
3543             return false;
3544     }
3545 
3546     if (!context->isValidBufferBinding(target))
3547     {
3548         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3549         return false;
3550     }
3551 
3552     Buffer *buffer = context->getState().getTargetBuffer(target);
3553 
3554     if (!buffer)
3555     {
3556         context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
3557         return false;
3558     }
3559 
3560     if (context->getExtensions().webglCompatibility &&
3561         buffer->isBoundForTransformFeedbackAndOtherUse())
3562     {
3563         context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3564         return false;
3565     }
3566 
3567     if (buffer->isImmutable())
3568     {
3569         context->validationError(GL_INVALID_OPERATION, kBufferImmutable);
3570         return false;
3571     }
3572 
3573     return true;
3574 }
3575 
ValidateBufferSubData(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr size,const void * data)3576 bool ValidateBufferSubData(const Context *context,
3577                            BufferBinding target,
3578                            GLintptr offset,
3579                            GLsizeiptr size,
3580                            const void *data)
3581 {
3582     if (size < 0)
3583     {
3584         context->validationError(GL_INVALID_VALUE, kNegativeSize);
3585         return false;
3586     }
3587 
3588     if (offset < 0)
3589     {
3590         context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3591         return false;
3592     }
3593 
3594     if (!context->isValidBufferBinding(target))
3595     {
3596         context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3597         return false;
3598     }
3599 
3600     Buffer *buffer = context->getState().getTargetBuffer(target);
3601 
3602     if (!buffer)
3603     {
3604         context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
3605         return false;
3606     }
3607 
3608     if (buffer->isMapped())
3609     {
3610         context->validationError(GL_INVALID_OPERATION, kBufferMapped);
3611         return false;
3612     }
3613 
3614     if (context->getExtensions().webglCompatibility &&
3615         buffer->isBoundForTransformFeedbackAndOtherUse())
3616     {
3617         context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3618         return false;
3619     }
3620 
3621     if (buffer->isImmutable() &&
3622         (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0)
3623     {
3624         context->validationError(GL_INVALID_OPERATION, kBufferNotUpdatable);
3625         return false;
3626     }
3627 
3628     // Check for possible overflow of size + offset
3629     angle::CheckedNumeric<size_t> checkedSize(size);
3630     checkedSize += offset;
3631     if (!checkedSize.IsValid())
3632     {
3633         context->validationError(GL_INVALID_VALUE, kParamOverflow);
3634         return false;
3635     }
3636 
3637     if (size + offset > buffer->getSize())
3638     {
3639         context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
3640         return false;
3641     }
3642 
3643     return true;
3644 }
3645 
ValidateRequestExtensionANGLE(const Context * context,const GLchar * name)3646 bool ValidateRequestExtensionANGLE(const Context *context, const GLchar *name)
3647 {
3648     if (!context->getExtensions().requestExtension)
3649     {
3650         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3651         return false;
3652     }
3653 
3654     if (!context->isExtensionRequestable(name))
3655     {
3656         context->validationError(GL_INVALID_OPERATION, kExtensionNotRequestable);
3657         return false;
3658     }
3659 
3660     return true;
3661 }
3662 
ValidateDisableExtensionANGLE(const Context * context,const GLchar * name)3663 bool ValidateDisableExtensionANGLE(const Context *context, const GLchar *name)
3664 {
3665     if (!context->getExtensions().requestExtension)
3666     {
3667         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3668         return false;
3669     }
3670 
3671     if (!context->isExtensionDisablable(name))
3672     {
3673         context->validationError(GL_INVALID_OPERATION, kExtensionNotDisablable);
3674         return false;
3675     }
3676 
3677     return true;
3678 }
3679 
ValidateActiveTexture(const Context * context,GLenum texture)3680 bool ValidateActiveTexture(const Context *context, GLenum texture)
3681 {
3682     if (context->getClientMajorVersion() < 2)
3683     {
3684         return ValidateMultitextureUnit(context, texture);
3685     }
3686 
3687     if (texture < GL_TEXTURE0 ||
3688         texture >
3689             GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1)
3690     {
3691         context->validationError(GL_INVALID_ENUM, kInvalidCombinedImageUnit);
3692         return false;
3693     }
3694 
3695     return true;
3696 }
3697 
ValidateAttachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)3698 bool ValidateAttachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
3699 {
3700     Program *programObject = GetValidProgram(context, program);
3701     if (!programObject)
3702     {
3703         return false;
3704     }
3705 
3706     Shader *shaderObject = GetValidShader(context, shader);
3707     if (!shaderObject)
3708     {
3709         return false;
3710     }
3711 
3712     if (programObject->getAttachedShader(shaderObject->getType()))
3713     {
3714         context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
3715         return false;
3716     }
3717 
3718     return true;
3719 }
3720 
ValidateBindAttribLocation(const Context * context,ShaderProgramID program,GLuint index,const GLchar * name)3721 bool ValidateBindAttribLocation(const Context *context,
3722                                 ShaderProgramID program,
3723                                 GLuint index,
3724                                 const GLchar *name)
3725 {
3726     if (index >= MAX_VERTEX_ATTRIBS)
3727     {
3728         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
3729         return false;
3730     }
3731 
3732     if (strncmp(name, "gl_", 3) == 0)
3733     {
3734         context->validationError(GL_INVALID_OPERATION, kNameBeginsWithGL);
3735         return false;
3736     }
3737 
3738     if (context->isWebGL())
3739     {
3740         const size_t length = strlen(name);
3741 
3742         if (!IsValidESSLString(name, length))
3743         {
3744             // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
3745             // for shader-related entry points
3746             context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
3747             return false;
3748         }
3749 
3750         if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
3751         {
3752             return false;
3753         }
3754     }
3755 
3756     return GetValidProgram(context, program) != nullptr;
3757 }
3758 
ValidateBindFramebuffer(const Context * context,GLenum target,FramebufferID framebuffer)3759 bool ValidateBindFramebuffer(const Context *context, GLenum target, FramebufferID framebuffer)
3760 {
3761     return ValidateBindFramebufferBase(context, target, framebuffer);
3762 }
3763 
ValidateBindRenderbuffer(const Context * context,GLenum target,RenderbufferID renderbuffer)3764 bool ValidateBindRenderbuffer(const Context *context, GLenum target, RenderbufferID renderbuffer)
3765 {
3766     return ValidateBindRenderbufferBase(context, target, renderbuffer);
3767 }
3768 
ValidBlendEquationMode(const Context * context,GLenum mode)3769 static bool ValidBlendEquationMode(const Context *context, GLenum mode)
3770 {
3771     switch (mode)
3772     {
3773         case GL_FUNC_ADD:
3774         case GL_FUNC_SUBTRACT:
3775         case GL_FUNC_REVERSE_SUBTRACT:
3776             return true;
3777 
3778         case GL_MIN:
3779         case GL_MAX:
3780             return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
3781 
3782         default:
3783             return false;
3784     }
3785 }
3786 
ValidateBlendColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)3787 bool ValidateBlendColor(const Context *context,
3788                         GLfloat red,
3789                         GLfloat green,
3790                         GLfloat blue,
3791                         GLfloat alpha)
3792 {
3793     return true;
3794 }
3795 
ValidateBlendEquation(const Context * context,GLenum mode)3796 bool ValidateBlendEquation(const Context *context, GLenum mode)
3797 {
3798     if (!ValidBlendEquationMode(context, mode))
3799     {
3800         context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3801         return false;
3802     }
3803 
3804     return true;
3805 }
3806 
ValidateBlendEquationSeparate(const Context * context,GLenum modeRGB,GLenum modeAlpha)3807 bool ValidateBlendEquationSeparate(const Context *context, GLenum modeRGB, GLenum modeAlpha)
3808 {
3809     if (!ValidBlendEquationMode(context, modeRGB))
3810     {
3811         context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3812         return false;
3813     }
3814 
3815     if (!ValidBlendEquationMode(context, modeAlpha))
3816     {
3817         context->validationError(GL_INVALID_ENUM, kInvalidBlendEquation);
3818         return false;
3819     }
3820 
3821     return true;
3822 }
3823 
ValidateBlendFunc(const Context * context,GLenum sfactor,GLenum dfactor)3824 bool ValidateBlendFunc(const Context *context, GLenum sfactor, GLenum dfactor)
3825 {
3826     return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
3827 }
3828 
ValidateBlendFuncSeparate(const Context * context,GLenum srcRGB,GLenum dstRGB,GLenum srcAlpha,GLenum dstAlpha)3829 bool ValidateBlendFuncSeparate(const Context *context,
3830                                GLenum srcRGB,
3831                                GLenum dstRGB,
3832                                GLenum srcAlpha,
3833                                GLenum dstAlpha)
3834 {
3835     if (!ValidSrcBlendFunc(context, srcRGB))
3836     {
3837         context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3838         return false;
3839     }
3840 
3841     if (!ValidDstBlendFunc(context, dstRGB))
3842     {
3843         context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3844         return false;
3845     }
3846 
3847     if (!ValidSrcBlendFunc(context, srcAlpha))
3848     {
3849         context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3850         return false;
3851     }
3852 
3853     if (!ValidDstBlendFunc(context, dstAlpha))
3854     {
3855         context->validationError(GL_INVALID_ENUM, kInvalidBlendFunction);
3856         return false;
3857     }
3858 
3859     if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
3860         context->getExtensions().webglCompatibility)
3861     {
3862         bool constantColorUsed =
3863             (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
3864              dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
3865 
3866         bool constantAlphaUsed =
3867             (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
3868              dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
3869 
3870         if (constantColorUsed && constantAlphaUsed)
3871         {
3872             if (context->getExtensions().webglCompatibility)
3873             {
3874                 context->validationError(GL_INVALID_OPERATION, kInvalidConstantColor);
3875                 return false;
3876             }
3877 
3878             WARN() << kConstantColorAlphaLimitation;
3879             context->validationError(GL_INVALID_OPERATION, kConstantColorAlphaLimitation);
3880             return false;
3881         }
3882     }
3883 
3884     return true;
3885 }
3886 
ValidateGetString(const Context * context,GLenum name)3887 bool ValidateGetString(const Context *context, GLenum name)
3888 {
3889     switch (name)
3890     {
3891         case GL_VENDOR:
3892         case GL_RENDERER:
3893         case GL_VERSION:
3894         case GL_SHADING_LANGUAGE_VERSION:
3895         case GL_EXTENSIONS:
3896             break;
3897 
3898         case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3899             if (!context->getExtensions().requestExtension)
3900             {
3901                 context->validationError(GL_INVALID_ENUM, kInvalidName);
3902                 return false;
3903             }
3904             break;
3905 
3906         case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
3907             if (!context->getExtensions().getSerializedContextStringANGLE)
3908             {
3909                 context->validationError(GL_INVALID_ENUM, kInvalidName);
3910                 return false;
3911             }
3912             break;
3913 
3914         default:
3915             context->validationError(GL_INVALID_ENUM, kInvalidName);
3916             return false;
3917     }
3918 
3919     return true;
3920 }
3921 
ValidateLineWidth(const Context * context,GLfloat width)3922 bool ValidateLineWidth(const Context *context, GLfloat width)
3923 {
3924     if (width <= 0.0f || isNaN(width))
3925     {
3926         context->validationError(GL_INVALID_VALUE, kInvalidWidth);
3927         return false;
3928     }
3929 
3930     return true;
3931 }
3932 
ValidateDepthRangef(const Context * context,GLfloat zNear,GLfloat zFar)3933 bool ValidateDepthRangef(const Context *context, GLfloat zNear, GLfloat zFar)
3934 {
3935     if (context->getExtensions().webglCompatibility && zNear > zFar)
3936     {
3937         context->validationError(GL_INVALID_OPERATION, kInvalidDepthRange);
3938         return false;
3939     }
3940 
3941     return true;
3942 }
3943 
ValidateRenderbufferStorage(const Context * context,GLenum target,GLenum internalformat,GLsizei width,GLsizei height)3944 bool ValidateRenderbufferStorage(const Context *context,
3945                                  GLenum target,
3946                                  GLenum internalformat,
3947                                  GLsizei width,
3948                                  GLsizei height)
3949 {
3950     return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
3951                                                      height);
3952 }
3953 
ValidateRenderbufferStorageMultisampleANGLE(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3954 bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
3955                                                  GLenum target,
3956                                                  GLsizei samples,
3957                                                  GLenum internalformat,
3958                                                  GLsizei width,
3959                                                  GLsizei height)
3960 {
3961     if (!context->getExtensions().framebufferMultisample)
3962     {
3963         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3964         return false;
3965     }
3966 
3967     // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
3968     // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
3969     // generated.
3970     if (samples > context->getCaps().maxSamples)
3971     {
3972         context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
3973         return false;
3974     }
3975 
3976     // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
3977     // the specified storage. This is different than ES 3.0 in which a sample number higher
3978     // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
3979     // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
3980     if (context->getClientMajorVersion() >= 3)
3981     {
3982         const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3983         if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3984         {
3985             context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
3986             return false;
3987         }
3988     }
3989 
3990     return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
3991                                                      width, height);
3992 }
3993 
ValidateCheckFramebufferStatus(const Context * context,GLenum target)3994 bool ValidateCheckFramebufferStatus(const Context *context, GLenum target)
3995 {
3996     if (!ValidFramebufferTarget(context, target))
3997     {
3998         context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
3999         return false;
4000     }
4001 
4002     return true;
4003 }
4004 
ValidateClearColor(const Context * context,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)4005 bool ValidateClearColor(const Context *context,
4006                         GLfloat red,
4007                         GLfloat green,
4008                         GLfloat blue,
4009                         GLfloat alpha)
4010 {
4011     return true;
4012 }
4013 
ValidateClearDepthf(const Context * context,GLfloat depth)4014 bool ValidateClearDepthf(const Context *context, GLfloat depth)
4015 {
4016     return true;
4017 }
4018 
ValidateClearStencil(const Context * context,GLint s)4019 bool ValidateClearStencil(const Context *context, GLint s)
4020 {
4021     return true;
4022 }
4023 
ValidateColorMask(const Context * context,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)4024 bool ValidateColorMask(const Context *context,
4025                        GLboolean red,
4026                        GLboolean green,
4027                        GLboolean blue,
4028                        GLboolean alpha)
4029 {
4030     return true;
4031 }
4032 
ValidateCompileShader(const Context * context,ShaderProgramID shader)4033 bool ValidateCompileShader(const Context *context, ShaderProgramID shader)
4034 {
4035     return true;
4036 }
4037 
ValidateCreateProgram(const Context * context)4038 bool ValidateCreateProgram(const Context *context)
4039 {
4040     return true;
4041 }
4042 
ValidateCullFace(const Context * context,CullFaceMode mode)4043 bool ValidateCullFace(const Context *context, CullFaceMode mode)
4044 {
4045     switch (mode)
4046     {
4047         case CullFaceMode::Front:
4048         case CullFaceMode::Back:
4049         case CullFaceMode::FrontAndBack:
4050             break;
4051 
4052         default:
4053             context->validationError(GL_INVALID_ENUM, kInvalidCullMode);
4054             return false;
4055     }
4056 
4057     return true;
4058 }
4059 
ValidateDeleteProgram(const Context * context,ShaderProgramID program)4060 bool ValidateDeleteProgram(const Context *context, ShaderProgramID program)
4061 {
4062     if (program.value == 0)
4063     {
4064         return false;
4065     }
4066 
4067     if (!context->getProgramResolveLink(program))
4068     {
4069         if (context->getShader(program))
4070         {
4071             context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
4072             return false;
4073         }
4074         else
4075         {
4076             context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
4077             return false;
4078         }
4079     }
4080 
4081     return true;
4082 }
4083 
ValidateDeleteShader(const Context * context,ShaderProgramID shader)4084 bool ValidateDeleteShader(const Context *context, ShaderProgramID shader)
4085 {
4086     if (shader.value == 0)
4087     {
4088         return false;
4089     }
4090 
4091     if (!context->getShader(shader))
4092     {
4093         if (context->getProgramResolveLink(shader))
4094         {
4095             context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
4096             return false;
4097         }
4098         else
4099         {
4100             context->validationError(GL_INVALID_VALUE, kExpectedShaderName);
4101             return false;
4102         }
4103     }
4104 
4105     return true;
4106 }
4107 
ValidateDepthFunc(const Context * context,GLenum func)4108 bool ValidateDepthFunc(const Context *context, GLenum func)
4109 {
4110     switch (func)
4111     {
4112         case GL_NEVER:
4113         case GL_ALWAYS:
4114         case GL_LESS:
4115         case GL_LEQUAL:
4116         case GL_EQUAL:
4117         case GL_GREATER:
4118         case GL_GEQUAL:
4119         case GL_NOTEQUAL:
4120             break;
4121 
4122         default:
4123             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4124             return false;
4125     }
4126 
4127     return true;
4128 }
4129 
ValidateDepthMask(const Context * context,GLboolean flag)4130 bool ValidateDepthMask(const Context *context, GLboolean flag)
4131 {
4132     return true;
4133 }
4134 
ValidateDetachShader(const Context * context,ShaderProgramID program,ShaderProgramID shader)4135 bool ValidateDetachShader(const Context *context, ShaderProgramID program, ShaderProgramID shader)
4136 {
4137     Program *programObject = GetValidProgram(context, program);
4138     if (!programObject)
4139     {
4140         return false;
4141     }
4142 
4143     Shader *shaderObject = GetValidShader(context, shader);
4144     if (!shaderObject)
4145     {
4146         return false;
4147     }
4148 
4149     const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
4150     if (attachedShader != shaderObject)
4151     {
4152         context->validationError(GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
4153         return false;
4154     }
4155 
4156     return true;
4157 }
4158 
ValidateDisableVertexAttribArray(const Context * context,GLuint index)4159 bool ValidateDisableVertexAttribArray(const Context *context, GLuint index)
4160 {
4161     if (index >= MAX_VERTEX_ATTRIBS)
4162     {
4163         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4164         return false;
4165     }
4166 
4167     return true;
4168 }
4169 
ValidateEnableVertexAttribArray(const Context * context,GLuint index)4170 bool ValidateEnableVertexAttribArray(const Context *context, GLuint index)
4171 {
4172     if (index >= MAX_VERTEX_ATTRIBS)
4173     {
4174         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
4175         return false;
4176     }
4177 
4178     return true;
4179 }
4180 
ValidateFinish(const Context * context)4181 bool ValidateFinish(const Context *context)
4182 {
4183     return true;
4184 }
4185 
ValidateFlush(const Context * context)4186 bool ValidateFlush(const Context *context)
4187 {
4188     return true;
4189 }
4190 
ValidateFrontFace(const Context * context,GLenum mode)4191 bool ValidateFrontFace(const Context *context, GLenum mode)
4192 {
4193     switch (mode)
4194     {
4195         case GL_CW:
4196         case GL_CCW:
4197             break;
4198         default:
4199             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4200             return false;
4201     }
4202 
4203     return true;
4204 }
4205 
ValidateGetActiveAttrib(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4206 bool ValidateGetActiveAttrib(const Context *context,
4207                              ShaderProgramID program,
4208                              GLuint index,
4209                              GLsizei bufsize,
4210                              const GLsizei *length,
4211                              const GLint *size,
4212                              const GLenum *type,
4213                              const GLchar *name)
4214 {
4215     if (bufsize < 0)
4216     {
4217         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4218         return false;
4219     }
4220 
4221     Program *programObject = GetValidProgram(context, program);
4222 
4223     if (!programObject)
4224     {
4225         return false;
4226     }
4227 
4228     if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
4229     {
4230         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4231         return false;
4232     }
4233 
4234     return true;
4235 }
4236 
ValidateGetActiveUniform(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufsize,const GLsizei * length,const GLint * size,const GLenum * type,const GLchar * name)4237 bool ValidateGetActiveUniform(const Context *context,
4238                               ShaderProgramID program,
4239                               GLuint index,
4240                               GLsizei bufsize,
4241                               const GLsizei *length,
4242                               const GLint *size,
4243                               const GLenum *type,
4244                               const GLchar *name)
4245 {
4246     if (bufsize < 0)
4247     {
4248         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4249         return false;
4250     }
4251 
4252     Program *programObject = GetValidProgram(context, program);
4253 
4254     if (!programObject)
4255     {
4256         return false;
4257     }
4258 
4259     if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
4260     {
4261         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4262         return false;
4263     }
4264 
4265     return true;
4266 }
4267 
ValidateGetAttachedShaders(const Context * context,ShaderProgramID program,GLsizei maxcount,const GLsizei * count,const ShaderProgramID * shaders)4268 bool ValidateGetAttachedShaders(const Context *context,
4269                                 ShaderProgramID program,
4270                                 GLsizei maxcount,
4271                                 const GLsizei *count,
4272                                 const ShaderProgramID *shaders)
4273 {
4274     if (maxcount < 0)
4275     {
4276         context->validationError(GL_INVALID_VALUE, kNegativeMaxCount);
4277         return false;
4278     }
4279 
4280     Program *programObject = GetValidProgram(context, program);
4281 
4282     if (!programObject)
4283     {
4284         return false;
4285     }
4286 
4287     return true;
4288 }
4289 
ValidateGetAttribLocation(const Context * context,ShaderProgramID program,const GLchar * name)4290 bool ValidateGetAttribLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4291 {
4292     // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4293     // shader-related entry points
4294     if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4295     {
4296         context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4297         return false;
4298     }
4299 
4300     Program *programObject = GetValidProgram(context, program);
4301 
4302     if (!programObject)
4303     {
4304         context->validationError(GL_INVALID_OPERATION, kProgramNotBound);
4305         return false;
4306     }
4307 
4308     if (!programObject->isLinked())
4309     {
4310         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4311         return false;
4312     }
4313 
4314     return true;
4315 }
4316 
ValidateGetBooleanv(const Context * context,GLenum pname,const GLboolean * params)4317 bool ValidateGetBooleanv(const Context *context, GLenum pname, const GLboolean *params)
4318 {
4319     GLenum nativeType;
4320     unsigned int numParams = 0;
4321     return ValidateStateQuery(context, pname, &nativeType, &numParams);
4322 }
4323 
ValidateGetError(const Context * context)4324 bool ValidateGetError(const Context *context)
4325 {
4326     return true;
4327 }
4328 
ValidateGetFloatv(const Context * context,GLenum pname,const GLfloat * params)4329 bool ValidateGetFloatv(const Context *context, GLenum pname, const GLfloat *params)
4330 {
4331     GLenum nativeType;
4332     unsigned int numParams = 0;
4333     return ValidateStateQuery(context, pname, &nativeType, &numParams);
4334 }
4335 
ValidateGetIntegerv(const Context * context,GLenum pname,const GLint * params)4336 bool ValidateGetIntegerv(const Context *context, GLenum pname, const GLint *params)
4337 {
4338     GLenum nativeType;
4339     unsigned int numParams = 0;
4340     return ValidateStateQuery(context, pname, &nativeType, &numParams);
4341 }
4342 
ValidateGetProgramInfoLog(const Context * context,ShaderProgramID program,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4343 bool ValidateGetProgramInfoLog(const Context *context,
4344                                ShaderProgramID program,
4345                                GLsizei bufsize,
4346                                const GLsizei *length,
4347                                const GLchar *infolog)
4348 {
4349     if (bufsize < 0)
4350     {
4351         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4352         return false;
4353     }
4354 
4355     Program *programObject = GetValidProgram(context, program);
4356     if (!programObject)
4357     {
4358         return false;
4359     }
4360 
4361     return true;
4362 }
4363 
ValidateGetShaderInfoLog(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * infolog)4364 bool ValidateGetShaderInfoLog(const Context *context,
4365                               ShaderProgramID shader,
4366                               GLsizei bufsize,
4367                               const GLsizei *length,
4368                               const GLchar *infolog)
4369 {
4370     if (bufsize < 0)
4371     {
4372         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4373         return false;
4374     }
4375 
4376     Shader *shaderObject = GetValidShader(context, shader);
4377     if (!shaderObject)
4378     {
4379         return false;
4380     }
4381 
4382     return true;
4383 }
4384 
ValidateGetShaderPrecisionFormat(const Context * context,GLenum shadertype,GLenum precisiontype,const GLint * range,const GLint * precision)4385 bool ValidateGetShaderPrecisionFormat(const Context *context,
4386                                       GLenum shadertype,
4387                                       GLenum precisiontype,
4388                                       const GLint *range,
4389                                       const GLint *precision)
4390 {
4391     switch (shadertype)
4392     {
4393         case GL_VERTEX_SHADER:
4394         case GL_FRAGMENT_SHADER:
4395             break;
4396         case GL_COMPUTE_SHADER:
4397             context->validationError(GL_INVALID_OPERATION, kUnimplementedComputeShaderPrecision);
4398             return false;
4399         default:
4400             context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
4401             return false;
4402     }
4403 
4404     switch (precisiontype)
4405     {
4406         case GL_LOW_FLOAT:
4407         case GL_MEDIUM_FLOAT:
4408         case GL_HIGH_FLOAT:
4409         case GL_LOW_INT:
4410         case GL_MEDIUM_INT:
4411         case GL_HIGH_INT:
4412             break;
4413 
4414         default:
4415             context->validationError(GL_INVALID_ENUM, kInvalidPrecision);
4416             return false;
4417     }
4418 
4419     return true;
4420 }
4421 
ValidateGetShaderSource(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)4422 bool ValidateGetShaderSource(const Context *context,
4423                              ShaderProgramID shader,
4424                              GLsizei bufsize,
4425                              const GLsizei *length,
4426                              const GLchar *source)
4427 {
4428     if (bufsize < 0)
4429     {
4430         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4431         return false;
4432     }
4433 
4434     Shader *shaderObject = GetValidShader(context, shader);
4435     if (!shaderObject)
4436     {
4437         return false;
4438     }
4439 
4440     return true;
4441 }
4442 
ValidateGetUniformLocation(const Context * context,ShaderProgramID program,const GLchar * name)4443 bool ValidateGetUniformLocation(const Context *context, ShaderProgramID program, const GLchar *name)
4444 {
4445     if (strstr(name, "gl_") == name)
4446     {
4447         return false;
4448     }
4449 
4450     // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
4451     // shader-related entry points
4452     if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
4453     {
4454         context->validationError(GL_INVALID_VALUE, kInvalidNameCharacters);
4455         return false;
4456     }
4457 
4458     Program *programObject = GetValidProgram(context, program);
4459 
4460     if (!programObject)
4461     {
4462         return false;
4463     }
4464 
4465     if (!programObject->isLinked())
4466     {
4467         context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4468         return false;
4469     }
4470 
4471     return true;
4472 }
4473 
ValidateHint(const Context * context,GLenum target,GLenum mode)4474 bool ValidateHint(const Context *context, GLenum target, GLenum mode)
4475 {
4476     switch (mode)
4477     {
4478         case GL_FASTEST:
4479         case GL_NICEST:
4480         case GL_DONT_CARE:
4481             break;
4482 
4483         default:
4484             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4485             return false;
4486     }
4487 
4488     switch (target)
4489     {
4490         case GL_GENERATE_MIPMAP_HINT:
4491             break;
4492 
4493         case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4494             if (!context->getExtensions().textureFilteringCHROMIUM)
4495             {
4496                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4497                 return false;
4498             }
4499             break;
4500 
4501         case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
4502             if (context->getClientVersion() < ES_3_0 &&
4503                 !context->getExtensions().standardDerivativesOES)
4504             {
4505                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4506                 return false;
4507             }
4508             break;
4509 
4510         case GL_PERSPECTIVE_CORRECTION_HINT:
4511         case GL_POINT_SMOOTH_HINT:
4512         case GL_LINE_SMOOTH_HINT:
4513         case GL_FOG_HINT:
4514             if (context->getClientMajorVersion() >= 2)
4515             {
4516                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4517                 return false;
4518             }
4519             break;
4520 
4521         default:
4522             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4523             return false;
4524     }
4525 
4526     return true;
4527 }
4528 
ValidateIsBuffer(const Context * context,BufferID buffer)4529 bool ValidateIsBuffer(const Context *context, BufferID buffer)
4530 {
4531     return true;
4532 }
4533 
ValidateIsFramebuffer(const Context * context,FramebufferID framebuffer)4534 bool ValidateIsFramebuffer(const Context *context, FramebufferID framebuffer)
4535 {
4536     return true;
4537 }
4538 
ValidateIsProgram(const Context * context,ShaderProgramID program)4539 bool ValidateIsProgram(const Context *context, ShaderProgramID program)
4540 {
4541     return true;
4542 }
4543 
ValidateIsRenderbuffer(const Context * context,RenderbufferID renderbuffer)4544 bool ValidateIsRenderbuffer(const Context *context, RenderbufferID renderbuffer)
4545 {
4546     return true;
4547 }
4548 
ValidateIsShader(const Context * context,ShaderProgramID shader)4549 bool ValidateIsShader(const Context *context, ShaderProgramID shader)
4550 {
4551     return true;
4552 }
4553 
ValidateIsTexture(const Context * context,TextureID texture)4554 bool ValidateIsTexture(const Context *context, TextureID texture)
4555 {
4556     return true;
4557 }
4558 
ValidatePixelStorei(const Context * context,GLenum pname,GLint param)4559 bool ValidatePixelStorei(const Context *context, GLenum pname, GLint param)
4560 {
4561     if (context->getClientMajorVersion() < 3)
4562     {
4563         switch (pname)
4564         {
4565             case GL_UNPACK_IMAGE_HEIGHT:
4566             case GL_UNPACK_SKIP_IMAGES:
4567                 context->validationError(GL_INVALID_ENUM, kInvalidPname);
4568                 return false;
4569 
4570             case GL_UNPACK_ROW_LENGTH:
4571             case GL_UNPACK_SKIP_ROWS:
4572             case GL_UNPACK_SKIP_PIXELS:
4573                 if (!context->getExtensions().unpackSubimage)
4574                 {
4575                     context->validationError(GL_INVALID_ENUM, kInvalidPname);
4576                     return false;
4577                 }
4578                 break;
4579 
4580             case GL_PACK_ROW_LENGTH:
4581             case GL_PACK_SKIP_ROWS:
4582             case GL_PACK_SKIP_PIXELS:
4583                 if (!context->getExtensions().packSubimage)
4584                 {
4585                     context->validationError(GL_INVALID_ENUM, kInvalidPname);
4586                     return false;
4587                 }
4588                 break;
4589         }
4590     }
4591 
4592     if (param < 0)
4593     {
4594         context->validationError(GL_INVALID_VALUE, kNegativeParam);
4595         return false;
4596     }
4597 
4598     switch (pname)
4599     {
4600         case GL_UNPACK_ALIGNMENT:
4601             if (param != 1 && param != 2 && param != 4 && param != 8)
4602             {
4603                 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
4604                 return false;
4605             }
4606             break;
4607 
4608         case GL_PACK_ALIGNMENT:
4609             if (param != 1 && param != 2 && param != 4 && param != 8)
4610             {
4611                 context->validationError(GL_INVALID_VALUE, kInvalidUnpackAlignment);
4612                 return false;
4613             }
4614             break;
4615 
4616         case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
4617             if (!context->getExtensions().packReverseRowOrder)
4618             {
4619                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4620             }
4621             break;
4622 
4623         case GL_UNPACK_ROW_LENGTH:
4624         case GL_UNPACK_IMAGE_HEIGHT:
4625         case GL_UNPACK_SKIP_IMAGES:
4626         case GL_UNPACK_SKIP_ROWS:
4627         case GL_UNPACK_SKIP_PIXELS:
4628         case GL_PACK_ROW_LENGTH:
4629         case GL_PACK_SKIP_ROWS:
4630         case GL_PACK_SKIP_PIXELS:
4631             break;
4632 
4633         default:
4634             context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4635             return false;
4636     }
4637 
4638     return true;
4639 }
4640 
ValidatePolygonOffset(const Context * context,GLfloat factor,GLfloat units)4641 bool ValidatePolygonOffset(const Context *context, GLfloat factor, GLfloat units)
4642 {
4643     return true;
4644 }
4645 
ValidateReleaseShaderCompiler(const Context * context)4646 bool ValidateReleaseShaderCompiler(const Context *context)
4647 {
4648     return true;
4649 }
4650 
ValidateSampleCoverage(const Context * context,GLfloat value,GLboolean invert)4651 bool ValidateSampleCoverage(const Context *context, GLfloat value, GLboolean invert)
4652 {
4653     return true;
4654 }
4655 
ValidateScissor(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)4656 bool ValidateScissor(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
4657 {
4658     if (width < 0 || height < 0)
4659     {
4660         context->validationError(GL_INVALID_VALUE, kNegativeSize);
4661         return false;
4662     }
4663 
4664     return true;
4665 }
4666 
ValidateShaderBinary(const Context * context,GLsizei n,const ShaderProgramID * shaders,GLenum binaryformat,const void * binary,GLsizei length)4667 bool ValidateShaderBinary(const Context *context,
4668                           GLsizei n,
4669                           const ShaderProgramID *shaders,
4670                           GLenum binaryformat,
4671                           const void *binary,
4672                           GLsizei length)
4673 {
4674     const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
4675     if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
4676         shaderBinaryFormats.end())
4677     {
4678         context->validationError(GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
4679         return false;
4680     }
4681 
4682     return true;
4683 }
4684 
ValidateShaderSource(const Context * context,ShaderProgramID shader,GLsizei count,const GLchar * const * string,const GLint * length)4685 bool ValidateShaderSource(const Context *context,
4686                           ShaderProgramID shader,
4687                           GLsizei count,
4688                           const GLchar *const *string,
4689                           const GLint *length)
4690 {
4691     if (count < 0)
4692     {
4693         context->validationError(GL_INVALID_VALUE, kNegativeCount);
4694         return false;
4695     }
4696 
4697     Shader *shaderObject = GetValidShader(context, shader);
4698     if (!shaderObject)
4699     {
4700         return false;
4701     }
4702 
4703     return true;
4704 }
4705 
ValidateStencilFunc(const Context * context,GLenum func,GLint ref,GLuint mask)4706 bool ValidateStencilFunc(const Context *context, GLenum func, GLint ref, GLuint mask)
4707 {
4708     if (!IsValidStencilFunc(func))
4709     {
4710         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4711         return false;
4712     }
4713 
4714     return true;
4715 }
4716 
ValidateStencilFuncSeparate(const Context * context,GLenum face,GLenum func,GLint ref,GLuint mask)4717 bool ValidateStencilFuncSeparate(const Context *context,
4718                                  GLenum face,
4719                                  GLenum func,
4720                                  GLint ref,
4721                                  GLuint mask)
4722 {
4723     if (!IsValidStencilFace(face))
4724     {
4725         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4726         return false;
4727     }
4728 
4729     if (!IsValidStencilFunc(func))
4730     {
4731         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4732         return false;
4733     }
4734 
4735     return true;
4736 }
4737 
ValidateStencilMask(const Context * context,GLuint mask)4738 bool ValidateStencilMask(const Context *context, GLuint mask)
4739 {
4740     return true;
4741 }
4742 
ValidateStencilMaskSeparate(const Context * context,GLenum face,GLuint mask)4743 bool ValidateStencilMaskSeparate(const Context *context, GLenum face, GLuint mask)
4744 {
4745     if (!IsValidStencilFace(face))
4746     {
4747         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4748         return false;
4749     }
4750 
4751     return true;
4752 }
4753 
ValidateStencilOp(const Context * context,GLenum fail,GLenum zfail,GLenum zpass)4754 bool ValidateStencilOp(const Context *context, GLenum fail, GLenum zfail, GLenum zpass)
4755 {
4756     if (!IsValidStencilOp(fail))
4757     {
4758         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4759         return false;
4760     }
4761 
4762     if (!IsValidStencilOp(zfail))
4763     {
4764         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4765         return false;
4766     }
4767 
4768     if (!IsValidStencilOp(zpass))
4769     {
4770         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4771         return false;
4772     }
4773 
4774     return true;
4775 }
4776 
ValidateStencilOpSeparate(const Context * context,GLenum face,GLenum fail,GLenum zfail,GLenum zpass)4777 bool ValidateStencilOpSeparate(const Context *context,
4778                                GLenum face,
4779                                GLenum fail,
4780                                GLenum zfail,
4781                                GLenum zpass)
4782 {
4783     if (!IsValidStencilFace(face))
4784     {
4785         context->validationError(GL_INVALID_ENUM, kInvalidStencil);
4786         return false;
4787     }
4788 
4789     return ValidateStencilOp(context, fail, zfail, zpass);
4790 }
4791 
ValidateUniform1f(const Context * context,UniformLocation location,GLfloat x)4792 bool ValidateUniform1f(const Context *context, UniformLocation location, GLfloat x)
4793 {
4794     return ValidateUniform(context, GL_FLOAT, location, 1);
4795 }
4796 
ValidateUniform1fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4797 bool ValidateUniform1fv(const Context *context,
4798                         UniformLocation location,
4799                         GLsizei count,
4800                         const GLfloat *v)
4801 {
4802     return ValidateUniform(context, GL_FLOAT, location, count);
4803 }
4804 
ValidateUniform1i(const Context * context,UniformLocation location,GLint x)4805 bool ValidateUniform1i(const Context *context, UniformLocation location, GLint x)
4806 {
4807     return ValidateUniform1iv(context, location, 1, &x);
4808 }
4809 
ValidateUniform2fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4810 bool ValidateUniform2fv(const Context *context,
4811                         UniformLocation location,
4812                         GLsizei count,
4813                         const GLfloat *v)
4814 {
4815     return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
4816 }
4817 
ValidateUniform2i(const Context * context,UniformLocation location,GLint x,GLint y)4818 bool ValidateUniform2i(const Context *context, UniformLocation location, GLint x, GLint y)
4819 {
4820     return ValidateUniform(context, GL_INT_VEC2, location, 1);
4821 }
4822 
ValidateUniform2iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)4823 bool ValidateUniform2iv(const Context *context,
4824                         UniformLocation location,
4825                         GLsizei count,
4826                         const GLint *v)
4827 {
4828     return ValidateUniform(context, GL_INT_VEC2, location, count);
4829 }
4830 
ValidateUniform3f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z)4831 bool ValidateUniform3f(const Context *context,
4832                        UniformLocation location,
4833                        GLfloat x,
4834                        GLfloat y,
4835                        GLfloat z)
4836 {
4837     return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
4838 }
4839 
ValidateUniform3fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4840 bool ValidateUniform3fv(const Context *context,
4841                         UniformLocation location,
4842                         GLsizei count,
4843                         const GLfloat *v)
4844 {
4845     return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
4846 }
4847 
ValidateUniform3i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z)4848 bool ValidateUniform3i(const Context *context, UniformLocation location, GLint x, GLint y, GLint z)
4849 {
4850     return ValidateUniform(context, GL_INT_VEC3, location, 1);
4851 }
4852 
ValidateUniform3iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)4853 bool ValidateUniform3iv(const Context *context,
4854                         UniformLocation location,
4855                         GLsizei count,
4856                         const GLint *v)
4857 {
4858     return ValidateUniform(context, GL_INT_VEC3, location, count);
4859 }
4860 
ValidateUniform4f(const Context * context,UniformLocation location,GLfloat x,GLfloat y,GLfloat z,GLfloat w)4861 bool ValidateUniform4f(const Context *context,
4862                        UniformLocation location,
4863                        GLfloat x,
4864                        GLfloat y,
4865                        GLfloat z,
4866                        GLfloat w)
4867 {
4868     return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
4869 }
4870 
ValidateUniform4fv(const Context * context,UniformLocation location,GLsizei count,const GLfloat * v)4871 bool ValidateUniform4fv(const Context *context,
4872                         UniformLocation location,
4873                         GLsizei count,
4874                         const GLfloat *v)
4875 {
4876     return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
4877 }
4878 
ValidateUniform4i(const Context * context,UniformLocation location,GLint x,GLint y,GLint z,GLint w)4879 bool ValidateUniform4i(const Context *context,
4880                        UniformLocation location,
4881                        GLint x,
4882                        GLint y,
4883                        GLint z,
4884                        GLint w)
4885 {
4886     return ValidateUniform(context, GL_INT_VEC4, location, 1);
4887 }
4888 
ValidateUniform4iv(const Context * context,UniformLocation location,GLsizei count,const GLint * v)4889 bool ValidateUniform4iv(const Context *context,
4890                         UniformLocation location,
4891                         GLsizei count,
4892                         const GLint *v)
4893 {
4894     return ValidateUniform(context, GL_INT_VEC4, location, count);
4895 }
4896 
ValidateUniformMatrix2fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4897 bool ValidateUniformMatrix2fv(const Context *context,
4898                               UniformLocation location,
4899                               GLsizei count,
4900                               GLboolean transpose,
4901                               const GLfloat *value)
4902 {
4903     return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
4904 }
4905 
ValidateUniformMatrix3fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4906 bool ValidateUniformMatrix3fv(const Context *context,
4907                               UniformLocation location,
4908                               GLsizei count,
4909                               GLboolean transpose,
4910                               const GLfloat *value)
4911 {
4912     return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
4913 }
4914 
ValidateUniformMatrix4fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4915 bool ValidateUniformMatrix4fv(const Context *context,
4916                               UniformLocation location,
4917                               GLsizei count,
4918                               GLboolean transpose,
4919                               const GLfloat *value)
4920 {
4921     return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
4922 }
4923 
ValidateValidateProgram(const Context * context,ShaderProgramID program)4924 bool ValidateValidateProgram(const Context *context, ShaderProgramID program)
4925 {
4926     Program *programObject = GetValidProgram(context, program);
4927 
4928     if (!programObject)
4929     {
4930         return false;
4931     }
4932 
4933     return true;
4934 }
4935 
ValidateVertexAttrib1f(const Context * context,GLuint index,GLfloat x)4936 bool ValidateVertexAttrib1f(const Context *context, GLuint index, GLfloat x)
4937 {
4938     return ValidateVertexAttribIndex(context, index);
4939 }
4940 
ValidateVertexAttrib1fv(const Context * context,GLuint index,const GLfloat * values)4941 bool ValidateVertexAttrib1fv(const Context *context, GLuint index, const GLfloat *values)
4942 {
4943     return ValidateVertexAttribIndex(context, index);
4944 }
4945 
ValidateVertexAttrib2f(const Context * context,GLuint index,GLfloat x,GLfloat y)4946 bool ValidateVertexAttrib2f(const Context *context, GLuint index, GLfloat x, GLfloat y)
4947 {
4948     return ValidateVertexAttribIndex(context, index);
4949 }
4950 
ValidateVertexAttrib2fv(const Context * context,GLuint index,const GLfloat * values)4951 bool ValidateVertexAttrib2fv(const Context *context, GLuint index, const GLfloat *values)
4952 {
4953     return ValidateVertexAttribIndex(context, index);
4954 }
4955 
ValidateVertexAttrib3f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z)4956 bool ValidateVertexAttrib3f(const Context *context, GLuint index, GLfloat x, GLfloat y, GLfloat z)
4957 {
4958     return ValidateVertexAttribIndex(context, index);
4959 }
4960 
ValidateVertexAttrib3fv(const Context * context,GLuint index,const GLfloat * values)4961 bool ValidateVertexAttrib3fv(const Context *context, GLuint index, const GLfloat *values)
4962 {
4963     return ValidateVertexAttribIndex(context, index);
4964 }
4965 
ValidateVertexAttrib4f(const Context * context,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)4966 bool ValidateVertexAttrib4f(const Context *context,
4967                             GLuint index,
4968                             GLfloat x,
4969                             GLfloat y,
4970                             GLfloat z,
4971                             GLfloat w)
4972 {
4973     return ValidateVertexAttribIndex(context, index);
4974 }
4975 
ValidateVertexAttrib4fv(const Context * context,GLuint index,const GLfloat * values)4976 bool ValidateVertexAttrib4fv(const Context *context, GLuint index, const GLfloat *values)
4977 {
4978     return ValidateVertexAttribIndex(context, index);
4979 }
4980 
ValidateViewport(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height)4981 bool ValidateViewport(const Context *context, GLint x, GLint y, GLsizei width, GLsizei height)
4982 {
4983     if (width < 0 || height < 0)
4984     {
4985         context->validationError(GL_INVALID_VALUE, kViewportNegativeSize);
4986         return false;
4987     }
4988 
4989     return true;
4990 }
4991 
ValidateGetFramebufferAttachmentParameteriv(const Context * context,GLenum target,GLenum attachment,GLenum pname,const GLint * params)4992 bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
4993                                                  GLenum target,
4994                                                  GLenum attachment,
4995                                                  GLenum pname,
4996                                                  const GLint *params)
4997 {
4998     return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4999                                                            nullptr);
5000 }
5001 
ValidateGetProgramiv(const Context * context,ShaderProgramID program,GLenum pname,const GLint * params)5002 bool ValidateGetProgramiv(const Context *context,
5003                           ShaderProgramID program,
5004                           GLenum pname,
5005                           const GLint *params)
5006 {
5007     return ValidateGetProgramivBase(context, program, pname, nullptr);
5008 }
5009 
ValidateCopyTexImage2D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)5010 bool ValidateCopyTexImage2D(const Context *context,
5011                             TextureTarget target,
5012                             GLint level,
5013                             GLenum internalformat,
5014                             GLint x,
5015                             GLint y,
5016                             GLsizei width,
5017                             GLsizei height,
5018                             GLint border)
5019 {
5020     if (context->getClientMajorVersion() < 3)
5021     {
5022         return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
5023                                                  0, x, y, width, height, border);
5024     }
5025 
5026     ASSERT(context->getClientMajorVersion() == 3);
5027     return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
5028                                                0, x, y, width, height, border);
5029 }
5030 
ValidateCopyTexSubImage2D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)5031 bool ValidateCopyTexSubImage2D(const Context *context,
5032                                TextureTarget target,
5033                                GLint level,
5034                                GLint xoffset,
5035                                GLint yoffset,
5036                                GLint x,
5037                                GLint y,
5038                                GLsizei width,
5039                                GLsizei height)
5040 {
5041     if (context->getClientMajorVersion() < 3)
5042     {
5043         return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
5044                                                  yoffset, x, y, width, height, 0);
5045     }
5046 
5047     return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
5048                                                yoffset, 0, x, y, width, height, 0);
5049 }
5050 
ValidateCopyTexSubImage3DOES(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)5051 bool ValidateCopyTexSubImage3DOES(const Context *context,
5052                                   TextureTarget target,
5053                                   GLint level,
5054                                   GLint xoffset,
5055                                   GLint yoffset,
5056                                   GLint zoffset,
5057                                   GLint x,
5058                                   GLint y,
5059                                   GLsizei width,
5060                                   GLsizei height)
5061 {
5062     return ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y, width,
5063                                      height);
5064 }
5065 
ValidateDeleteBuffers(const Context * context,GLint n,const BufferID * buffers)5066 bool ValidateDeleteBuffers(const Context *context, GLint n, const BufferID *buffers)
5067 {
5068     return ValidateGenOrDelete(context, n);
5069 }
5070 
ValidateDeleteFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5071 bool ValidateDeleteFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5072 {
5073     return ValidateGenOrDelete(context, n);
5074 }
5075 
ValidateDeleteRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5076 bool ValidateDeleteRenderbuffers(const Context *context,
5077                                  GLint n,
5078                                  const RenderbufferID *renderbuffers)
5079 {
5080     return ValidateGenOrDelete(context, n);
5081 }
5082 
ValidateDeleteTextures(const Context * context,GLint n,const TextureID * textures)5083 bool ValidateDeleteTextures(const Context *context, GLint n, const TextureID *textures)
5084 {
5085     return ValidateGenOrDelete(context, n);
5086 }
5087 
ValidateDisable(const Context * context,GLenum cap)5088 bool ValidateDisable(const Context *context, GLenum cap)
5089 {
5090     if (!ValidCap(context, cap, false))
5091     {
5092         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5093         return false;
5094     }
5095 
5096     return true;
5097 }
5098 
ValidateEnable(const Context * context,GLenum cap)5099 bool ValidateEnable(const Context *context, GLenum cap)
5100 {
5101     if (!ValidCap(context, cap, false))
5102     {
5103         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5104         return false;
5105     }
5106 
5107     if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5108         cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5109     {
5110         context->validationError(GL_INVALID_OPERATION, kNoSampleAlphaToCoveragesLimitation);
5111 
5112         // We also output an error message to the debugger window if tracing is active, so that
5113         // developers can see the error message.
5114         ERR() << kNoSampleAlphaToCoveragesLimitation;
5115         return false;
5116     }
5117 
5118     return true;
5119 }
5120 
ValidateFramebufferRenderbuffer(const Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)5121 bool ValidateFramebufferRenderbuffer(const Context *context,
5122                                      GLenum target,
5123                                      GLenum attachment,
5124                                      GLenum renderbuffertarget,
5125                                      RenderbufferID renderbuffer)
5126 {
5127     return ValidateFramebufferRenderbufferBase(context, target, attachment, renderbuffertarget,
5128                                                renderbuffer);
5129 }
5130 
ValidateFramebufferTexture2D(const Context * context,GLenum target,GLenum attachment,TextureTarget textarget,TextureID texture,GLint level)5131 bool ValidateFramebufferTexture2D(const Context *context,
5132                                   GLenum target,
5133                                   GLenum attachment,
5134                                   TextureTarget textarget,
5135                                   TextureID texture,
5136                                   GLint level)
5137 {
5138     // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
5139     // extension
5140     if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5141         level != 0)
5142     {
5143         context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5144         return false;
5145     }
5146 
5147     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5148     {
5149         return false;
5150     }
5151 
5152     if (texture.value != 0)
5153     {
5154         Texture *tex = context->getTexture(texture);
5155         ASSERT(tex);
5156 
5157         const Caps &caps = context->getCaps();
5158 
5159         switch (textarget)
5160         {
5161             case TextureTarget::_2D:
5162             {
5163                 if (level > log2(caps.max2DTextureSize))
5164                 {
5165                     context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5166                     return false;
5167                 }
5168                 if (tex->getType() != TextureType::_2D)
5169                 {
5170                     context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5171                     return false;
5172                 }
5173             }
5174             break;
5175 
5176             case TextureTarget::Rectangle:
5177             {
5178                 if (level != 0)
5179                 {
5180                     context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5181                     return false;
5182                 }
5183                 if (tex->getType() != TextureType::Rectangle)
5184                 {
5185                     context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5186                     return false;
5187                 }
5188             }
5189             break;
5190 
5191             case TextureTarget::CubeMapNegativeX:
5192             case TextureTarget::CubeMapNegativeY:
5193             case TextureTarget::CubeMapNegativeZ:
5194             case TextureTarget::CubeMapPositiveX:
5195             case TextureTarget::CubeMapPositiveY:
5196             case TextureTarget::CubeMapPositiveZ:
5197             {
5198                 if (level > log2(caps.maxCubeMapTextureSize))
5199                 {
5200                     context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5201                     return false;
5202                 }
5203                 if (tex->getType() != TextureType::CubeMap)
5204                 {
5205                     context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5206                     return false;
5207                 }
5208             }
5209             break;
5210 
5211             case TextureTarget::_2DMultisample:
5212             {
5213                 if (context->getClientVersion() < ES_3_1 &&
5214                     !context->getExtensions().textureMultisample)
5215                 {
5216                     context->validationError(GL_INVALID_OPERATION,
5217                                              kMultisampleTextureExtensionOrES31Required);
5218                     return false;
5219                 }
5220 
5221                 if (level != 0)
5222                 {
5223                     context->validationError(GL_INVALID_VALUE, kLevelNotZero);
5224                     return false;
5225                 }
5226                 if (tex->getType() != TextureType::_2DMultisample)
5227                 {
5228                     context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5229                     return false;
5230                 }
5231             }
5232             break;
5233 
5234             case TextureTarget::External:
5235             {
5236                 if (!context->getExtensions().yuvTargetEXT)
5237                 {
5238                     context->validationError(GL_INVALID_OPERATION, kYUVTargetExtensionRequired);
5239                     return false;
5240                 }
5241 
5242                 if (attachment != GL_COLOR_ATTACHMENT0)
5243                 {
5244                     context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
5245                     return false;
5246                 }
5247 
5248                 if (tex->getType() != TextureType::External)
5249                 {
5250                     context->validationError(GL_INVALID_OPERATION, kTextureTargetMismatch);
5251                     return false;
5252                 }
5253             }
5254             break;
5255 
5256             default:
5257                 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5258                 return false;
5259         }
5260     }
5261 
5262     return true;
5263 }
5264 
ValidateFramebufferTexture3DOES(const Context * context,GLenum target,GLenum attachment,TextureTarget textargetPacked,TextureID texture,GLint level,GLint zoffset)5265 bool ValidateFramebufferTexture3DOES(const Context *context,
5266                                      GLenum target,
5267                                      GLenum attachment,
5268                                      TextureTarget textargetPacked,
5269                                      TextureID texture,
5270                                      GLint level,
5271                                      GLint zoffset)
5272 {
5273     // We don't call into a base ValidateFramebufferTexture3D here because
5274     // it doesn't exist for OpenGL ES. This function is replaced by
5275     // FramebufferTextureLayer in ES 3.x, which has broader support.
5276     if (!context->getExtensions().texture3DOES)
5277     {
5278         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5279         return false;
5280     }
5281 
5282     // Attachments are required to be bound to level 0 without ES3 or the
5283     // GL_OES_fbo_render_mipmap extension
5284     if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
5285         level != 0)
5286     {
5287         context->validationError(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
5288         return false;
5289     }
5290 
5291     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
5292     {
5293         return false;
5294     }
5295 
5296     if (texture.value != 0)
5297     {
5298         Texture *tex = context->getTexture(texture);
5299         ASSERT(tex);
5300 
5301         const Caps &caps = context->getCaps();
5302 
5303         switch (textargetPacked)
5304         {
5305             case TextureTarget::_3D:
5306             {
5307                 if (level > log2(caps.max3DTextureSize))
5308                 {
5309                     context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
5310                     return false;
5311                 }
5312                 if (zoffset >= caps.max3DTextureSize)
5313                 {
5314                     context->validationError(GL_INVALID_VALUE, kInvalidZOffset);
5315                     return false;
5316                 }
5317                 if (tex->getType() != TextureType::_3D)
5318                 {
5319                     context->validationError(GL_INVALID_OPERATION, kInvalidTextureType);
5320                     return false;
5321                 }
5322             }
5323             break;
5324 
5325             default:
5326                 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
5327                 return false;
5328         }
5329     }
5330 
5331     return true;
5332 }
5333 
ValidateGenBuffers(const Context * context,GLint n,const BufferID * buffers)5334 bool ValidateGenBuffers(const Context *context, GLint n, const BufferID *buffers)
5335 {
5336     return ValidateGenOrDelete(context, n);
5337 }
5338 
ValidateGenFramebuffers(const Context * context,GLint n,const FramebufferID * framebuffers)5339 bool ValidateGenFramebuffers(const Context *context, GLint n, const FramebufferID *framebuffers)
5340 {
5341     return ValidateGenOrDelete(context, n);
5342 }
5343 
ValidateGenRenderbuffers(const Context * context,GLint n,const RenderbufferID * renderbuffers)5344 bool ValidateGenRenderbuffers(const Context *context, GLint n, const RenderbufferID *renderbuffers)
5345 {
5346     return ValidateGenOrDelete(context, n);
5347 }
5348 
ValidateGenTextures(const Context * context,GLint n,const TextureID * textures)5349 bool ValidateGenTextures(const Context *context, GLint n, const TextureID *textures)
5350 {
5351     return ValidateGenOrDelete(context, n);
5352 }
5353 
ValidateGenerateMipmap(const Context * context,TextureType target)5354 bool ValidateGenerateMipmap(const Context *context, TextureType target)
5355 {
5356     return ValidateGenerateMipmapBase(context, target);
5357 }
5358 
ValidateGetBufferParameteriv(const Context * context,BufferBinding target,GLenum pname,const GLint * params)5359 bool ValidateGetBufferParameteriv(const Context *context,
5360                                   BufferBinding target,
5361                                   GLenum pname,
5362                                   const GLint *params)
5363 {
5364     return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5365 }
5366 
ValidateGetRenderbufferParameteriv(const Context * context,GLenum target,GLenum pname,const GLint * params)5367 bool ValidateGetRenderbufferParameteriv(const Context *context,
5368                                         GLenum target,
5369                                         GLenum pname,
5370                                         const GLint *params)
5371 {
5372     return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5373 }
5374 
ValidateGetShaderiv(const Context * context,ShaderProgramID shader,GLenum pname,const GLint * params)5375 bool ValidateGetShaderiv(const Context *context,
5376                          ShaderProgramID shader,
5377                          GLenum pname,
5378                          const GLint *params)
5379 {
5380     return ValidateGetShaderivBase(context, shader, pname, nullptr);
5381 }
5382 
ValidateGetTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)5383 bool ValidateGetTexParameterfv(const Context *context,
5384                                TextureType target,
5385                                GLenum pname,
5386                                const GLfloat *params)
5387 {
5388     return ValidateGetTexParameterBase(context, target, pname, nullptr);
5389 }
5390 
ValidateGetTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)5391 bool ValidateGetTexParameteriv(const Context *context,
5392                                TextureType target,
5393                                GLenum pname,
5394                                const GLint *params)
5395 {
5396     return ValidateGetTexParameterBase(context, target, pname, nullptr);
5397 }
5398 
ValidateGetTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)5399 bool ValidateGetTexParameterIivOES(const Context *context,
5400                                    TextureType target,
5401                                    GLenum pname,
5402                                    const GLint *params)
5403 {
5404     if (context->getClientMajorVersion() < 3)
5405     {
5406         context->validationError(GL_INVALID_OPERATION, kES3Required);
5407         return false;
5408     }
5409     return ValidateGetTexParameterBase(context, target, pname, nullptr);
5410 }
5411 
ValidateGetTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)5412 bool ValidateGetTexParameterIuivOES(const Context *context,
5413                                     TextureType target,
5414                                     GLenum pname,
5415                                     const GLuint *params)
5416 {
5417     if (context->getClientMajorVersion() < 3)
5418     {
5419         context->validationError(GL_INVALID_OPERATION, kES3Required);
5420         return false;
5421     }
5422     return ValidateGetTexParameterBase(context, target, pname, nullptr);
5423 }
5424 
ValidateGetUniformfv(const Context * context,ShaderProgramID program,UniformLocation location,const GLfloat * params)5425 bool ValidateGetUniformfv(const Context *context,
5426                           ShaderProgramID program,
5427                           UniformLocation location,
5428                           const GLfloat *params)
5429 {
5430     return ValidateGetUniformBase(context, program, location);
5431 }
5432 
ValidateGetUniformiv(const Context * context,ShaderProgramID program,UniformLocation location,const GLint * params)5433 bool ValidateGetUniformiv(const Context *context,
5434                           ShaderProgramID program,
5435                           UniformLocation location,
5436                           const GLint *params)
5437 {
5438     return ValidateGetUniformBase(context, program, location);
5439 }
5440 
ValidateGetVertexAttribfv(const Context * context,GLuint index,GLenum pname,const GLfloat * params)5441 bool ValidateGetVertexAttribfv(const Context *context,
5442                                GLuint index,
5443                                GLenum pname,
5444                                const GLfloat *params)
5445 {
5446     return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5447 }
5448 
ValidateGetVertexAttribiv(const Context * context,GLuint index,GLenum pname,const GLint * params)5449 bool ValidateGetVertexAttribiv(const Context *context,
5450                                GLuint index,
5451                                GLenum pname,
5452                                const GLint *params)
5453 {
5454     return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5455 }
5456 
ValidateGetVertexAttribPointerv(const Context * context,GLuint index,GLenum pname,void * const * pointer)5457 bool ValidateGetVertexAttribPointerv(const Context *context,
5458                                      GLuint index,
5459                                      GLenum pname,
5460                                      void *const *pointer)
5461 {
5462     return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5463 }
5464 
ValidateIsEnabled(const Context * context,GLenum cap)5465 bool ValidateIsEnabled(const Context *context, GLenum cap)
5466 {
5467     if (!ValidCap(context, cap, true))
5468     {
5469         context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5470         return false;
5471     }
5472 
5473     return true;
5474 }
5475 
ValidateLinkProgram(const Context * context,ShaderProgramID program)5476 bool ValidateLinkProgram(const Context *context, ShaderProgramID program)
5477 {
5478     if (context->hasActiveTransformFeedback(program))
5479     {
5480         // ES 3.0.4 section 2.15 page 91
5481         context->validationError(GL_INVALID_OPERATION, kTransformFeedbackActiveDuringLink);
5482         return false;
5483     }
5484 
5485     Program *programObject = GetValidProgram(context, program);
5486     if (!programObject)
5487     {
5488         return false;
5489     }
5490 
5491     return true;
5492 }
5493 
ValidateReadPixels(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)5494 bool ValidateReadPixels(const Context *context,
5495                         GLint x,
5496                         GLint y,
5497                         GLsizei width,
5498                         GLsizei height,
5499                         GLenum format,
5500                         GLenum type,
5501                         const void *pixels)
5502 {
5503     return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
5504                                   nullptr, pixels);
5505 }
5506 
ValidateTexParameterf(const Context * context,TextureType target,GLenum pname,GLfloat param)5507 bool ValidateTexParameterf(const Context *context, TextureType target, GLenum pname, GLfloat param)
5508 {
5509     return ValidateTexParameterBase(context, target, pname, -1, false, &param);
5510 }
5511 
ValidateTexParameterfv(const Context * context,TextureType target,GLenum pname,const GLfloat * params)5512 bool ValidateTexParameterfv(const Context *context,
5513                             TextureType target,
5514                             GLenum pname,
5515                             const GLfloat *params)
5516 {
5517     return ValidateTexParameterBase(context, target, pname, -1, true, params);
5518 }
5519 
ValidateTexParameteri(const Context * context,TextureType target,GLenum pname,GLint param)5520 bool ValidateTexParameteri(const Context *context, TextureType target, GLenum pname, GLint param)
5521 {
5522     return ValidateTexParameterBase(context, target, pname, -1, false, &param);
5523 }
5524 
ValidateTexParameteriv(const Context * context,TextureType target,GLenum pname,const GLint * params)5525 bool ValidateTexParameteriv(const Context *context,
5526                             TextureType target,
5527                             GLenum pname,
5528                             const GLint *params)
5529 {
5530     return ValidateTexParameterBase(context, target, pname, -1, true, params);
5531 }
5532 
ValidateTexParameterIivOES(const Context * context,TextureType target,GLenum pname,const GLint * params)5533 bool ValidateTexParameterIivOES(const Context *context,
5534                                 TextureType target,
5535                                 GLenum pname,
5536                                 const GLint *params)
5537 {
5538     if (context->getClientMajorVersion() < 3)
5539     {
5540         context->validationError(GL_INVALID_OPERATION, kES3Required);
5541         return false;
5542     }
5543     return ValidateTexParameterBase(context, target, pname, -1, true, params);
5544 }
5545 
ValidateTexParameterIuivOES(const Context * context,TextureType target,GLenum pname,const GLuint * params)5546 bool ValidateTexParameterIuivOES(const Context *context,
5547                                  TextureType target,
5548                                  GLenum pname,
5549                                  const GLuint *params)
5550 {
5551     if (context->getClientMajorVersion() < 3)
5552     {
5553         context->validationError(GL_INVALID_OPERATION, kES3Required);
5554         return false;
5555     }
5556     return ValidateTexParameterBase(context, target, pname, -1, true, params);
5557 }
5558 
ValidateUseProgram(const Context * context,ShaderProgramID program)5559 bool ValidateUseProgram(const Context *context, ShaderProgramID program)
5560 {
5561     if (program.value != 0)
5562     {
5563         Program *programObject = context->getProgramResolveLink(program);
5564         if (!programObject)
5565         {
5566             // ES 3.1.0 section 7.3 page 72
5567             if (context->getShader(program))
5568             {
5569                 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
5570                 return false;
5571             }
5572             else
5573             {
5574                 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
5575                 return false;
5576             }
5577         }
5578         if (!programObject->isLinked())
5579         {
5580             context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
5581             return false;
5582         }
5583     }
5584     if (context->getState().isTransformFeedbackActiveUnpaused())
5585     {
5586         // ES 3.0.4 section 2.15 page 91
5587         context->validationError(GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
5588         return false;
5589     }
5590 
5591     return true;
5592 }
5593 
ValidateDeleteFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)5594 bool ValidateDeleteFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
5595 {
5596     if (!context->getExtensions().fenceNV)
5597     {
5598         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5599         return false;
5600     }
5601 
5602     if (n < 0)
5603     {
5604         context->validationError(GL_INVALID_VALUE, kNegativeCount);
5605         return false;
5606     }
5607 
5608     return true;
5609 }
5610 
ValidateFinishFenceNV(const Context * context,FenceNVID fence)5611 bool ValidateFinishFenceNV(const Context *context, FenceNVID fence)
5612 {
5613     if (!context->getExtensions().fenceNV)
5614     {
5615         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5616         return false;
5617     }
5618 
5619     FenceNV *fenceObject = context->getFenceNV(fence);
5620 
5621     if (fenceObject == nullptr)
5622     {
5623         context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5624         return false;
5625     }
5626 
5627     if (!fenceObject->isSet())
5628     {
5629         context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5630         return false;
5631     }
5632 
5633     return true;
5634 }
5635 
ValidateGenFencesNV(const Context * context,GLsizei n,const FenceNVID * fences)5636 bool ValidateGenFencesNV(const Context *context, GLsizei n, const FenceNVID *fences)
5637 {
5638     if (!context->getExtensions().fenceNV)
5639     {
5640         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5641         return false;
5642     }
5643 
5644     if (n < 0)
5645     {
5646         context->validationError(GL_INVALID_VALUE, kNegativeCount);
5647         return false;
5648     }
5649 
5650     return true;
5651 }
5652 
ValidateGetFenceivNV(const Context * context,FenceNVID fence,GLenum pname,const GLint * params)5653 bool ValidateGetFenceivNV(const Context *context,
5654                           FenceNVID fence,
5655                           GLenum pname,
5656                           const GLint *params)
5657 {
5658     if (!context->getExtensions().fenceNV)
5659     {
5660         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5661         return false;
5662     }
5663 
5664     FenceNV *fenceObject = context->getFenceNV(fence);
5665 
5666     if (fenceObject == nullptr)
5667     {
5668         context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5669         return false;
5670     }
5671 
5672     if (!fenceObject->isSet())
5673     {
5674         context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5675         return false;
5676     }
5677 
5678     switch (pname)
5679     {
5680         case GL_FENCE_STATUS_NV:
5681         case GL_FENCE_CONDITION_NV:
5682             break;
5683 
5684         default:
5685             context->validationError(GL_INVALID_ENUM, kInvalidPname);
5686             return false;
5687     }
5688 
5689     return true;
5690 }
5691 
ValidateGetGraphicsResetStatusEXT(const Context * context)5692 bool ValidateGetGraphicsResetStatusEXT(const Context *context)
5693 {
5694     if (!context->getExtensions().robustness)
5695     {
5696         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5697         return false;
5698     }
5699 
5700     return true;
5701 }
5702 
ValidateGetTranslatedShaderSourceANGLE(const Context * context,ShaderProgramID shader,GLsizei bufsize,const GLsizei * length,const GLchar * source)5703 bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
5704                                             ShaderProgramID shader,
5705                                             GLsizei bufsize,
5706                                             const GLsizei *length,
5707                                             const GLchar *source)
5708 {
5709     if (!context->getExtensions().translatedShaderSource)
5710     {
5711         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5712         return false;
5713     }
5714 
5715     if (bufsize < 0)
5716     {
5717         context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
5718         return false;
5719     }
5720 
5721     Shader *shaderObject = context->getShader(shader);
5722 
5723     if (!shaderObject)
5724     {
5725         context->validationError(GL_INVALID_OPERATION, kInvalidShaderName);
5726         return false;
5727     }
5728 
5729     return true;
5730 }
5731 
ValidateIsFenceNV(const Context * context,FenceNVID fence)5732 bool ValidateIsFenceNV(const Context *context, FenceNVID fence)
5733 {
5734     if (!context->getExtensions().fenceNV)
5735     {
5736         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5737         return false;
5738     }
5739 
5740     return true;
5741 }
5742 
ValidateSetFenceNV(const Context * context,FenceNVID fence,GLenum condition)5743 bool ValidateSetFenceNV(const Context *context, FenceNVID fence, GLenum condition)
5744 {
5745     if (!context->getExtensions().fenceNV)
5746     {
5747         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5748         return false;
5749     }
5750 
5751     if (condition != GL_ALL_COMPLETED_NV)
5752     {
5753         context->validationError(GL_INVALID_ENUM, kInvalidFenceCondition);
5754         return false;
5755     }
5756 
5757     FenceNV *fenceObject = context->getFenceNV(fence);
5758 
5759     if (fenceObject == nullptr)
5760     {
5761         context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5762         return false;
5763     }
5764 
5765     return true;
5766 }
5767 
ValidateTestFenceNV(const Context * context,FenceNVID fence)5768 bool ValidateTestFenceNV(const Context *context, FenceNVID fence)
5769 {
5770     if (!context->getExtensions().fenceNV)
5771     {
5772         context->validationError(GL_INVALID_OPERATION, kNVFenceNotSupported);
5773         return false;
5774     }
5775 
5776     FenceNV *fenceObject = context->getFenceNV(fence);
5777 
5778     if (fenceObject == nullptr)
5779     {
5780         context->validationError(GL_INVALID_OPERATION, kInvalidFence);
5781         return false;
5782     }
5783 
5784     if (fenceObject->isSet() != GL_TRUE)
5785     {
5786         context->validationError(GL_INVALID_OPERATION, kInvalidFenceState);
5787         return false;
5788     }
5789 
5790     return true;
5791 }
5792 
ValidateTexStorage2DEXT(const Context * context,TextureType type,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)5793 bool ValidateTexStorage2DEXT(const Context *context,
5794                              TextureType type,
5795                              GLsizei levels,
5796                              GLenum internalformat,
5797                              GLsizei width,
5798                              GLsizei height)
5799 {
5800     if (!context->getExtensions().textureStorage)
5801     {
5802         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5803         return false;
5804     }
5805 
5806     if (context->getClientMajorVersion() < 3)
5807     {
5808         return ValidateES2TexStorageParametersBase(context, type, levels, internalformat, width,
5809                                                    height);
5810     }
5811 
5812     ASSERT(context->getClientMajorVersion() >= 3);
5813     return ValidateES3TexStorage2DParameters(context, type, levels, internalformat, width, height,
5814                                              1);
5815 }
5816 
ValidateVertexAttribDivisorANGLE(const Context * context,GLuint index,GLuint divisor)5817 bool ValidateVertexAttribDivisorANGLE(const Context *context, GLuint index, GLuint divisor)
5818 {
5819     if (!context->getExtensions().instancedArraysANGLE)
5820     {
5821         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5822         return false;
5823     }
5824 
5825     if (index >= MAX_VERTEX_ATTRIBS)
5826     {
5827         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
5828         return false;
5829     }
5830 
5831     if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
5832     {
5833         if (index == 0 && divisor != 0)
5834         {
5835             context->validationError(GL_INVALID_OPERATION, kAttributeZeroRequiresDivisorLimitation);
5836 
5837             // We also output an error message to the debugger window if tracing is active, so
5838             // that developers can see the error message.
5839             ERR() << kAttributeZeroRequiresDivisorLimitation;
5840             return false;
5841         }
5842     }
5843 
5844     return true;
5845 }
5846 
ValidateVertexAttribDivisorEXT(const Context * context,GLuint index,GLuint divisor)5847 bool ValidateVertexAttribDivisorEXT(const Context *context, GLuint index, GLuint divisor)
5848 {
5849     if (!context->getExtensions().instancedArraysEXT)
5850     {
5851         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5852         return false;
5853     }
5854 
5855     if (index >= MAX_VERTEX_ATTRIBS)
5856     {
5857         context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
5858         return false;
5859     }
5860 
5861     return true;
5862 }
5863 
ValidateTexImage3DOES(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)5864 bool ValidateTexImage3DOES(const Context *context,
5865                            TextureTarget target,
5866                            GLint level,
5867                            GLenum internalformat,
5868                            GLsizei width,
5869                            GLsizei height,
5870                            GLsizei depth,
5871                            GLint border,
5872                            GLenum format,
5873                            GLenum type,
5874                            const void *pixels)
5875 {
5876     return ValidateTexImage3D(context, target, level, internalformat, width, height, depth, border,
5877                               format, type, pixels);
5878 }
5879 
ValidatePopGroupMarkerEXT(const Context * context)5880 bool ValidatePopGroupMarkerEXT(const Context *context)
5881 {
5882     if (!context->getExtensions().debugMarker)
5883     {
5884         // The debug marker calls should not set error state
5885         // However, it seems reasonable to set an error state if the extension is not enabled
5886         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5887         return false;
5888     }
5889 
5890     return true;
5891 }
5892 
ValidateTexStorage1DEXT(const Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width)5893 bool ValidateTexStorage1DEXT(const Context *context,
5894                              GLenum target,
5895                              GLsizei levels,
5896                              GLenum internalformat,
5897                              GLsizei width)
5898 {
5899     UNIMPLEMENTED();
5900     context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5901     return false;
5902 }
5903 
ValidateTexStorage3DEXT(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)5904 bool ValidateTexStorage3DEXT(const Context *context,
5905                              TextureType target,
5906                              GLsizei levels,
5907                              GLenum internalformat,
5908                              GLsizei width,
5909                              GLsizei height,
5910                              GLsizei depth)
5911 {
5912     if (!context->getExtensions().textureStorage)
5913     {
5914         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5915         return false;
5916     }
5917 
5918     if (context->getClientMajorVersion() < 3)
5919     {
5920         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5921         return false;
5922     }
5923 
5924     return ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
5925                                              depth);
5926 }
5927 
ValidateMaxShaderCompilerThreadsKHR(const Context * context,GLuint count)5928 bool ValidateMaxShaderCompilerThreadsKHR(const Context *context, GLuint count)
5929 {
5930     if (!context->getExtensions().parallelShaderCompile)
5931     {
5932         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5933         return false;
5934     }
5935     return true;
5936 }
5937 
ValidateMultiDrawArraysANGLE(const Context * context,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)5938 bool ValidateMultiDrawArraysANGLE(const Context *context,
5939                                   PrimitiveMode mode,
5940                                   const GLint *firsts,
5941                                   const GLsizei *counts,
5942                                   GLsizei drawcount)
5943 {
5944     if (!context->getExtensions().multiDraw)
5945     {
5946         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5947         return false;
5948     }
5949     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
5950     {
5951         if (!ValidateDrawArrays(context, mode, firsts[drawID], counts[drawID]))
5952         {
5953             return false;
5954         }
5955     }
5956     return true;
5957 }
5958 
ValidateMultiDrawElementsANGLE(const Context * context,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)5959 bool ValidateMultiDrawElementsANGLE(const Context *context,
5960                                     PrimitiveMode mode,
5961                                     const GLsizei *counts,
5962                                     DrawElementsType type,
5963                                     const GLvoid *const *indices,
5964                                     GLsizei drawcount)
5965 {
5966     if (!context->getExtensions().multiDraw)
5967     {
5968         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5969         return false;
5970     }
5971     for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
5972     {
5973         if (!ValidateDrawElements(context, mode, counts[drawID], type, indices[drawID]))
5974         {
5975             return false;
5976         }
5977     }
5978     return true;
5979 }
5980 
ValidateProvokingVertexANGLE(const Context * context,ProvokingVertexConvention modePacked)5981 bool ValidateProvokingVertexANGLE(const Context *context, ProvokingVertexConvention modePacked)
5982 {
5983     if (!context->getExtensions().provokingVertex)
5984     {
5985         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5986         return false;
5987     }
5988 
5989     switch (modePacked)
5990     {
5991         case ProvokingVertexConvention::FirstVertexConvention:
5992         case ProvokingVertexConvention::LastVertexConvention:
5993             break;
5994         default:
5995             context->validationError(GL_INVALID_ENUM, kInvalidProvokingVertex);
5996             return false;
5997     }
5998 
5999     return true;
6000 }
6001 
ValidateFramebufferTexture2DMultisampleEXT(const Context * context,GLenum target,GLenum attachment,TextureTarget textarget,TextureID texture,GLint level,GLsizei samples)6002 bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
6003                                                 GLenum target,
6004                                                 GLenum attachment,
6005                                                 TextureTarget textarget,
6006                                                 TextureID texture,
6007                                                 GLint level,
6008                                                 GLsizei samples)
6009 {
6010     if (!context->getExtensions().multisampledRenderToTexture)
6011     {
6012         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6013         return false;
6014     }
6015 
6016     if (samples < 0)
6017     {
6018         return false;
6019     }
6020 
6021     // EXT_multisampled_render_to_texture states that the value of samples
6022     // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6023     // otherwise GL_INVALID_VALUE is generated.
6024     if (samples > context->getCaps().maxSamples)
6025     {
6026         context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6027         return false;
6028     }
6029 
6030     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
6031     {
6032         return false;
6033     }
6034 
6035     // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than
6036     // the maximum sample number supported by this format is passed.
6037     // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
6038     if (texture.value != 0 && context->getClientMajorVersion() >= 3)
6039     {
6040         Texture *tex                  = context->getTexture(texture);
6041         GLenum internalformat         = tex->getFormat(textarget, level).info->internalFormat;
6042         const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6043         if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6044         {
6045             context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
6046             return false;
6047         }
6048     }
6049 
6050     // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used.
6051     if (!context->getExtensions().multisampledRenderToTexture2 &&
6052         attachment != GL_COLOR_ATTACHMENT0)
6053     {
6054         context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
6055         return false;
6056     }
6057 
6058     if (!ValidTexture2DDestinationTarget(context, textarget))
6059     {
6060         context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6061         return false;
6062     }
6063 
6064     return true;
6065 }
6066 
ValidateRenderbufferStorageMultisampleEXT(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)6067 bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
6068                                                GLenum target,
6069                                                GLsizei samples,
6070                                                GLenum internalformat,
6071                                                GLsizei width,
6072                                                GLsizei height)
6073 {
6074     if (!context->getExtensions().multisampledRenderToTexture)
6075     {
6076         context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6077         return false;
6078     }
6079     if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
6080                                                    height))
6081     {
6082         return false;
6083     }
6084 
6085     // EXT_multisampled_render_to_texture states that the value of samples
6086     // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
6087     // otherwise GL_INVALID_VALUE is generated.
6088     if (samples > context->getCaps().maxSamples)
6089     {
6090         context->validationError(GL_INVALID_VALUE, kSamplesOutOfRange);
6091         return false;
6092     }
6093 
6094     // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create
6095     // the specified storage. This is different than ES 3.0 in which a sample number higher
6096     // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
6097     // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
6098     if (context->getClientMajorVersion() >= 3)
6099     {
6100         const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6101         if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6102         {
6103             context->validationError(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
6104             return false;
6105         }
6106     }
6107 
6108     return true;
6109 }
6110 
RecordBindTextureTypeError(const Context * context,TextureType target)6111 void RecordBindTextureTypeError(const Context *context, TextureType target)
6112 {
6113     ASSERT(!context->getStateCache().isValidBindTextureType(target));
6114 
6115     switch (target)
6116     {
6117         case TextureType::Rectangle:
6118             ASSERT(!context->getExtensions().textureRectangle);
6119             context->validationError(GL_INVALID_ENUM, kTextureRectangleNotSupported);
6120             break;
6121 
6122         case TextureType::_3D:
6123         case TextureType::_2DArray:
6124             ASSERT(context->getClientMajorVersion() < 3);
6125             context->validationError(GL_INVALID_ENUM, kES3Required);
6126             break;
6127 
6128         case TextureType::_2DMultisample:
6129             ASSERT(context->getClientVersion() < Version(3, 1) &&
6130                    !context->getExtensions().textureMultisample);
6131             context->validationError(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
6132             break;
6133 
6134         case TextureType::_2DMultisampleArray:
6135             ASSERT(!context->getExtensions().textureStorageMultisample2DArrayOES);
6136             context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
6137             break;
6138 
6139         case TextureType::External:
6140             ASSERT(!context->getExtensions().eglImageExternalOES &&
6141                    !context->getExtensions().eglStreamConsumerExternalNV);
6142             context->validationError(GL_INVALID_ENUM, kExternalTextureNotSupported);
6143             break;
6144 
6145         case TextureType::VideoImage:
6146             ASSERT(!context->getExtensions().webglVideoTexture);
6147             context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6148             break;
6149 
6150         case TextureType::Buffer:
6151             ASSERT(!context->getExtensions().textureBufferOES &&
6152                    !context->getExtensions().textureBufferEXT);
6153             context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6154             break;
6155 
6156         default:
6157             context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6158     }
6159 }
6160 
6161 }  // namespace gl
6162