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