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