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