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