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