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