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