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