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