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