1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
9 #include "libANGLE/validationES3_autogen.h"
10
11 #include "anglebase/numerics/safe_conversions.h"
12 #include "common/mathutil.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/ErrorStrings.h"
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 #include "libANGLE/PixelLocalStorage.h"
19 #include "libANGLE/Renderbuffer.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/VertexArray.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/validationES.h"
24 #include "libANGLE/validationES3.h"
25
26 using namespace angle;
27
28 namespace gl
29 {
30 using namespace err;
31
32 namespace
33 {
ValidateFramebufferTextureMultiviewBaseANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLsizei numViews)34 bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context,
35 angle::EntryPoint entryPoint,
36 GLenum target,
37 GLenum attachment,
38 TextureID texture,
39 GLint level,
40 GLsizei numViews)
41 {
42 if (!(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
43 {
44 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultiviewNotAvailable);
45 return false;
46 }
47
48 if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
49 {
50 return false;
51 }
52
53 if (texture.value != 0 && numViews < 1)
54 {
55 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMultiviewViewsTooSmall);
56 return false;
57 }
58
59 if (static_cast<GLuint>(numViews) > context->getCaps().maxViews)
60 {
61 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMultiviewViewsTooLarge);
62 return false;
63 }
64
65 return true;
66 }
67
ValidateFramebufferTextureMultiviewLevelAndFormat(const Context * context,angle::EntryPoint entryPoint,const Texture * texture,GLint level)68 bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context,
69 angle::EntryPoint entryPoint,
70 const Texture *texture,
71 GLint level)
72 {
73 TextureType type = texture->getType();
74 if (!ValidMipLevel(context, type, level))
75 {
76 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
77 return false;
78 }
79
80 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
81 if (format.info->compressed)
82 {
83 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
84 return false;
85 }
86 return true;
87 }
88
ValidateUniformES3(const Context * context,angle::EntryPoint entryPoint,GLenum uniformType,UniformLocation location,GLint count)89 bool ValidateUniformES3(const Context *context,
90 angle::EntryPoint entryPoint,
91 GLenum uniformType,
92 UniformLocation location,
93 GLint count)
94 {
95 if (context->getClientMajorVersion() < 3)
96 {
97 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
98 return false;
99 }
100
101 return ValidateUniform(context, entryPoint, uniformType, location, count);
102 }
103
ValidateUniformMatrixES3(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)104 bool ValidateUniformMatrixES3(const Context *context,
105 angle::EntryPoint entryPoint,
106 GLenum valueType,
107 UniformLocation location,
108 GLsizei count,
109 GLboolean transpose)
110 {
111 // Check for ES3 uniform entry points
112 if (context->getClientMajorVersion() < 3)
113 {
114 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
115 return false;
116 }
117
118 return ValidateUniformMatrix(context, entryPoint, valueType, location, count, transpose);
119 }
120
ValidateGenOrDeleteES3(const Context * context,angle::EntryPoint entryPoint,GLint n)121 bool ValidateGenOrDeleteES3(const Context *context, angle::EntryPoint entryPoint, GLint n)
122 {
123 if (context->getClientMajorVersion() < 3)
124 {
125 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
126 return false;
127 }
128 return ValidateGenOrDelete(context, entryPoint, n);
129 }
130
ValidateGenOrDeleteCountES3(const Context * context,angle::EntryPoint entryPoint,GLint count)131 bool ValidateGenOrDeleteCountES3(const Context *context, angle::EntryPoint entryPoint, GLint count)
132 {
133 if (context->getClientMajorVersion() < 3)
134 {
135 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
136 return false;
137 }
138 if (count < 0)
139 {
140 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
141 return false;
142 }
143 return true;
144 }
145
ValidateCopyTexture3DCommon(const Context * context,angle::EntryPoint entryPoint,const Texture * source,GLint sourceLevel,GLint srcInternalFormat,const Texture * dest,GLint destLevel,GLint internalFormat,TextureTarget destTarget)146 bool ValidateCopyTexture3DCommon(const Context *context,
147 angle::EntryPoint entryPoint,
148 const Texture *source,
149 GLint sourceLevel,
150 GLint srcInternalFormat,
151 const Texture *dest,
152 GLint destLevel,
153 GLint internalFormat,
154 TextureTarget destTarget)
155 {
156 if (context->getClientMajorVersion() < 3)
157 {
158 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
159 return false;
160 }
161
162 if (!context->getExtensions().copyTexture3dANGLE)
163 {
164 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable);
165 return false;
166 }
167
168 if (!ValidTexture3DTarget(context, source->getType()))
169 {
170 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
171 return false;
172 }
173
174 // Table 1.1 from the ANGLE_copy_texture_3d spec
175 switch (GetUnsizedFormat(srcInternalFormat))
176 {
177 case GL_ALPHA:
178 case GL_LUMINANCE:
179 case GL_LUMINANCE_ALPHA:
180 case GL_RED:
181 case GL_RED_INTEGER:
182 case GL_RG:
183 case GL_RG_INTEGER:
184 case GL_RGB:
185 case GL_RGB_INTEGER:
186 case GL_RGBA:
187 case GL_RGBA_INTEGER:
188 case GL_DEPTH_COMPONENT:
189 case GL_DEPTH_STENCIL:
190 break;
191 default:
192 ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat,
193 srcInternalFormat);
194 return false;
195 }
196
197 if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
198 {
199 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
200 return false;
201 }
202
203 // Table 1.0 from the ANGLE_copy_texture_3d spec
204 switch (internalFormat)
205 {
206 case GL_RGB:
207 case GL_RGBA:
208 case GL_LUMINANCE:
209 case GL_LUMINANCE_ALPHA:
210 case GL_ALPHA:
211 case GL_R8:
212 case GL_R8_SNORM:
213 case GL_R16F:
214 case GL_R32F:
215 case GL_R8UI:
216 case GL_R8I:
217 case GL_R16UI:
218 case GL_R16I:
219 case GL_R32UI:
220 case GL_R32I:
221 case GL_RG:
222 case GL_RG8:
223 case GL_RG8_SNORM:
224 case GL_RG16F:
225 case GL_RG32F:
226 case GL_RG8UI:
227 case GL_RG8I:
228 case GL_RG16UI:
229 case GL_RG16I:
230 case GL_RG32UI:
231 case GL_RG32I:
232 case GL_RGB8:
233 case GL_RGBX8_ANGLE:
234 case GL_SRGB8:
235 case GL_RGB565:
236 case GL_RGB8_SNORM:
237 case GL_R11F_G11F_B10F:
238 case GL_RGB9_E5:
239 case GL_RGB16F:
240 case GL_RGB32F:
241 case GL_RGB8UI:
242 case GL_RGB8I:
243 case GL_RGB16UI:
244 case GL_RGB16I:
245 case GL_RGB32UI:
246 case GL_RGB32I:
247 case GL_RGBA8:
248 case GL_SRGB8_ALPHA8:
249 case GL_RGBA8_SNORM:
250 case GL_RGB5_A1:
251 case GL_RGBA4:
252 case GL_RGB10_A2:
253 case GL_RGBA16F:
254 case GL_RGBA32F:
255 case GL_RGBA8UI:
256 case GL_RGBA8I:
257 case GL_RGB10_A2UI:
258 case GL_RGBA16UI:
259 case GL_RGBA16I:
260 case GL_RGBA32I:
261 case GL_RGBA32UI:
262 break;
263 default:
264 ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
265 return false;
266 }
267
268 return true;
269 }
270
ValidateColorMaskForSharedExponentColorBuffer(const Context * context,angle::EntryPoint entryPoint,GLint drawbuffer)271 bool ValidateColorMaskForSharedExponentColorBuffer(const Context *context,
272 angle::EntryPoint entryPoint,
273 GLint drawbuffer)
274 {
275 const State &state = context->getState();
276 const FramebufferAttachment *attachment = state.getDrawFramebuffer()->getDrawBuffer(drawbuffer);
277 if (attachment && attachment->getFormat().info->internalFormat == GL_RGB9_E5)
278 {
279 bool r, g, b, a;
280 state.getBlendStateExt().getColorMaskIndexed(drawbuffer, &r, &g, &b, &a);
281 if (r != g || g != b)
282 {
283 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
284 kUnsupportedColorMaskForSharedExponentColorBuffer);
285 return false;
286 }
287 }
288
289 return true;
290 }
291 } // anonymous namespace
292
ValidateTexImageFormatCombination(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum internalFormat,GLenum format,GLenum type)293 static bool ValidateTexImageFormatCombination(const Context *context,
294 angle::EntryPoint entryPoint,
295 TextureType target,
296 GLenum internalFormat,
297 GLenum format,
298 GLenum type)
299 {
300 // Different validation if on desktop api
301 if (context->getClientType() == EGL_OPENGL_API)
302 {
303 // The type and format are valid if any supported internal format has that type and format
304 if (!ValidDesktopFormat(format))
305 {
306 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
307 return false;
308 }
309
310 if (!ValidDesktopType(type))
311 {
312 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
313 return false;
314 }
315 }
316 else
317 {
318 // The type and format are valid if any supported internal format has that type and format.
319 // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
320 if (gl::IsYuvFormat(format))
321 {
322 if (!context->getExtensions().yuvInternalFormatANGLE)
323 {
324 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
325 return false;
326 }
327 }
328 else
329 {
330 if (!ValidES3Format(format))
331 {
332 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
333 return false;
334 }
335 }
336
337 if (!ValidES3Type(type) || (type == GL_HALF_FLOAT_OES && context->isWebGL()))
338 {
339 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
340 return false;
341 }
342 }
343
344 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
345 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
346 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
347 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
348 if (!ValidES3InternalFormat(internalFormat))
349 {
350 ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kInvalidInternalFormat, internalFormat);
351 return false;
352 }
353
354 // From the ES 3.0 spec section 3.8.3:
355 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
356 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
357 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
358 // INVALID_OPERATION error.
359 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
360 {
361 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, k3DDepthStencil);
362 return false;
363 }
364
365 if (context->getClientType() == EGL_OPENGL_API)
366 {
367 // Check if this is a valid format combination to load texture data
368 if (!ValidDesktopFormatCombination(format, type, internalFormat))
369 {
370 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
371 return false;
372 }
373 }
374 else
375 {
376 // Check if this is a valid format combination to load texture data
377 // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
378 if (gl::IsYuvFormat(format))
379 {
380 if (type != GL_UNSIGNED_BYTE)
381 {
382 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
383 return false;
384 }
385 }
386 else
387 {
388 if (!ValidES3FormatCombination(format, type, internalFormat))
389 {
390 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
391 return false;
392 }
393 }
394 }
395
396 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat, type);
397 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
398 {
399 ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
400 return false;
401 }
402
403 return true;
404 }
405
ValidateES3CompressedFormatForTexture2DArray(const Context * context,angle::EntryPoint entryPoint,GLenum format)406 static bool ValidateES3CompressedFormatForTexture2DArray(const Context *context,
407 angle::EntryPoint entryPoint,
408 GLenum format)
409 {
410 if ((IsETC1Format(format) && !context->getExtensions().compressedETC1RGB8SubTextureEXT) ||
411 IsPVRTC1Format(format))
412 {
413 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2D);
414 return false;
415 }
416
417 return true;
418 }
419
ValidateES3CompressedFormatForTexture3D(const Context * context,angle::EntryPoint entryPoint,GLenum format)420 static bool ValidateES3CompressedFormatForTexture3D(const Context *context,
421 angle::EntryPoint entryPoint,
422 GLenum format)
423 {
424 if (IsETC1Format(format) || IsPVRTC1Format(format))
425 {
426 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2D);
427 return false;
428 }
429
430 if (IsETC2EACFormat(format))
431 {
432 // ES 3.1, Section 8.7, page 169.
433 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArray);
434 return false;
435 }
436
437 if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionAstcHdrKHR ||
438 context->getExtensions().textureCompressionAstcSliced3dKHR))
439 {
440 // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
441 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayASTC);
442 return false;
443 }
444
445 if (IsS3TCFormat(format))
446 {
447 // GL_EXT_texture_compression_s3tc
448 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayS3TC);
449 return false;
450 }
451
452 if (IsRGTCFormat(format))
453 {
454 // GL_EXT_texture_compression_rgtc
455 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayRGTC);
456 return false;
457 }
458
459 if (IsBPTCFormat(format) && (context->getLimitations().noCompressedTexture3D))
460 {
461 // GL_EXT_texture_compression_bptc
462 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayBPTC);
463 return false;
464 }
465
466 return true;
467 }
468
ValidateES3TexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)469 bool ValidateES3TexImageParametersBase(const Context *context,
470 angle::EntryPoint entryPoint,
471 TextureTarget target,
472 GLint level,
473 GLenum internalformat,
474 bool isCompressed,
475 bool isSubImage,
476 GLint xoffset,
477 GLint yoffset,
478 GLint zoffset,
479 GLsizei width,
480 GLsizei height,
481 GLsizei depth,
482 GLint border,
483 GLenum format,
484 GLenum type,
485 GLsizei imageSize,
486 const void *pixels)
487 {
488 TextureType texType = TextureTargetToType(target);
489
490 if (gl::IsYuvFormat(format))
491 {
492 // According to ANGLE_yuv_internal_format, the texture needs to be an immutable
493 // texture, texture target can only be TEXTURE_2D and there is no mipmap support
494 if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
495 {
496 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
497 return false;
498 }
499
500 if (target != TextureTarget::_2D)
501 {
502 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
503 return false;
504 }
505
506 if (level != 0)
507 {
508 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
509 return false;
510 }
511 }
512
513 // Validate image size
514 if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, depth,
515 isSubImage))
516 {
517 // Error already processed.
518 return false;
519 }
520
521 // Verify zero border
522 if (border != 0)
523 {
524 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
525 return false;
526 }
527
528 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
529 {
530 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
531 return false;
532 }
533
534 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
535 std::numeric_limits<GLsizei>::max() - yoffset < height ||
536 std::numeric_limits<GLsizei>::max() - zoffset < depth)
537 {
538 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
539 return false;
540 }
541
542 const Caps &caps = context->getCaps();
543
544 switch (texType)
545 {
546 case TextureType::_2D:
547 case TextureType::External:
548 case TextureType::VideoImage:
549 if (width > (caps.max2DTextureSize >> level) ||
550 height > (caps.max2DTextureSize >> level))
551 {
552 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
553 return false;
554 }
555 break;
556
557 case TextureType::Rectangle:
558 ASSERT(level == 0);
559 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
560 {
561 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
562 return false;
563 }
564 if (isCompressed)
565 {
566 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRectangleTextureCompressed);
567 return false;
568 }
569 break;
570
571 case TextureType::CubeMap:
572 if (!isSubImage && width != height)
573 {
574 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
575 return false;
576 }
577
578 if (width > (caps.maxCubeMapTextureSize >> level))
579 {
580 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
581 return false;
582 }
583 break;
584
585 case TextureType::_3D:
586 if (width > (caps.max3DTextureSize >> level) ||
587 height > (caps.max3DTextureSize >> level) ||
588 depth > (caps.max3DTextureSize >> level))
589 {
590 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
591 return false;
592 }
593 break;
594
595 case TextureType::_2DArray:
596 if (width > (caps.max2DTextureSize >> level) ||
597 height > (caps.max2DTextureSize >> level) || depth > caps.maxArrayTextureLayers)
598 {
599 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
600 return false;
601 }
602 break;
603
604 case TextureType::CubeMapArray:
605 if (!isSubImage && width != height)
606 {
607 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
608 return false;
609 }
610
611 if (width > (caps.maxCubeMapTextureSize >> level))
612 {
613 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
614 return false;
615 }
616
617 if (width > (caps.max3DTextureSize >> level) ||
618 height > (caps.max3DTextureSize >> level) ||
619 depth > (caps.max3DTextureSize >> level))
620 {
621 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
622 return false;
623 }
624
625 if (!isSubImage && depth % 6 != 0)
626 {
627 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth);
628 return false;
629 }
630 break;
631
632 case TextureType::InvalidEnum:
633 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid);
634 return false;
635 default:
636 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(texType));
637 return false;
638 }
639
640 Texture *texture = context->getTextureByType(texType);
641 if (!texture)
642 {
643 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
644 return false;
645 }
646
647 if (texture->getImmutableFormat() && !isSubImage)
648 {
649 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
650 return false;
651 }
652
653 // Validate texture formats
654 GLenum actualInternalFormat =
655 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
656 if (isSubImage && actualInternalFormat == GL_NONE)
657 {
658 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMipLevel);
659 return false;
660 }
661
662 const InternalFormat &actualFormatInfo = isSubImage
663 ? *texture->getFormat(target, level).info
664 : GetInternalFormatInfo(internalformat, type);
665 if (isCompressed)
666 {
667 // compressedTexSubImage does not generate GL_INVALID_ENUM when format is unknown or invalid
668 if (!isSubImage)
669 {
670 if (!actualFormatInfo.compressed && !actualFormatInfo.paletted)
671 {
672 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kCompressedMismatch);
673 return false;
674 }
675
676 if (!actualFormatInfo.textureSupport(context->getClientVersion(),
677 context->getExtensions()))
678 {
679 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
680 return false;
681 }
682 }
683
684 if (texType == TextureType::_2DArray)
685 {
686 GLenum compressedDataFormat = isSubImage ? format : internalformat;
687 if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
688 compressedDataFormat))
689 {
690 // Error already generated.
691 return false;
692 }
693 }
694
695 if (texType == TextureType::_3D)
696 {
697 GLenum compressedDataFormat = isSubImage ? format : internalformat;
698 if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint, compressedDataFormat))
699 {
700 // Error already generated.
701 return false;
702 }
703 }
704
705 if (isSubImage)
706 {
707 if (!ValidCompressedSubImageSize(
708 context, actualFormatInfo.internalFormat, xoffset, yoffset, zoffset, width,
709 height, depth, texture->getWidth(target, level),
710 texture->getHeight(target, level), texture->getDepth(target, level)))
711 {
712 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
713 return false;
714 }
715
716 if (format != actualInternalFormat)
717 {
718 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedFormat);
719 return false;
720 }
721
722 // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
723 if (IsETC1Format(actualInternalFormat) &&
724 !context->getExtensions().compressedETC1RGB8SubTextureEXT)
725 {
726 ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat,
727 internalformat);
728 return false;
729 }
730 }
731 else
732 {
733 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height,
734 depth))
735 {
736 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
737 return false;
738 }
739 }
740
741 // Disallow 3D-only compressed formats from being set on 2D textures
742 if (actualFormatInfo.compressedBlockDepth > 1 && texType != TextureType::_3D)
743 {
744 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
745 return false;
746 }
747 }
748 else
749 {
750 // Compressed formats are not valid internal formats for glTexImage*D
751 if (!isSubImage)
752 {
753 const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(internalformat);
754 if (internalFormatInfo.compressed)
755 {
756 ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kInvalidInternalFormat, internalformat);
757 return false;
758 }
759 }
760
761 if (!ValidateTexImageFormatCombination(context, entryPoint, texType, actualInternalFormat,
762 format, type))
763 {
764 return false;
765 }
766 }
767
768 // Validate sub image parameters
769 if (isSubImage)
770 {
771 if (isCompressed != actualFormatInfo.compressed)
772 {
773 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedMismatch);
774 return false;
775 }
776
777 // Already validated above
778 ASSERT(xoffset >= 0 && yoffset >= 0 && zoffset >= 0);
779 ASSERT(std::numeric_limits<GLsizei>::max() - xoffset >= width &&
780 std::numeric_limits<GLsizei>::max() - yoffset >= height &&
781 std::numeric_limits<GLsizei>::max() - zoffset >= depth);
782
783 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
784 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
785 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
786 {
787 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
788 return false;
789 }
790
791 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
792 context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
793 {
794 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
795 return false;
796 }
797 }
798
799 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
800 if (!ValidImageDataSize(context, entryPoint, texType, width, height, depth, sizeCheckFormat,
801 type, pixels, imageSize))
802 {
803 return false;
804 }
805
806 // Check for pixel unpack buffer related API errors
807 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
808 if (pixelUnpackBuffer != nullptr)
809 {
810 // ...data is not evenly divisible into the number of bytes needed to store in memory a
811 // datum
812 // indicated by type.
813 if (!isCompressed)
814 {
815 size_t offset = reinterpret_cast<size_t>(pixels);
816 size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
817
818 if ((offset % dataBytesPerPixel) != 0)
819 {
820 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDataTypeNotAligned);
821 return false;
822 }
823 }
824
825 // ...the buffer object's data store is currently mapped but not persistently.
826 if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
827 {
828 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
829 return false;
830 }
831 }
832
833 if (context->getExtensions().webglCompatibilityANGLE)
834 {
835 // Define:
836 // DataStoreWidth = (GL_UNPACK_ROW_LENGTH ? GL_UNPACK_ROW_LENGTH : width)
837 // DataStoreHeight = (GL_UNPACK_IMAGE_HEIGHT ? GL_UNPACK_IMAGE_HEIGHT : height)
838 //
839 // WebGL 2.0 imposes the following additional constraints:
840 //
841 // 1) texImage2D and texSubImage2D generate INVALID_OPERATION if:
842 // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
843 // except for texImage2D if no GL_PIXEL_UNPACK_BUFFER is
844 // bound and _pixels_ is null.
845 //
846 // 2) texImage3D and texSubImage3D generate INVALID_OPERATION if:
847 // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
848 // GL_UNPACK_SKIP_ROWS + height > DataStoreHeight
849 // except for texImage3D if no GL_PIXEL_UNPACK_BUFFER is
850 // bound and _pixels_ is null.
851 if (!pixelUnpackBuffer && !pixels && !isSubImage)
852 {
853 // Exception case for texImage2D or texImage3D, above.
854 }
855 else
856 {
857 const auto &unpack = context->getState().getUnpackState();
858 GLint dataStoreWidth = unpack.rowLength ? unpack.rowLength : width;
859 if (unpack.skipPixels + width > dataStoreWidth)
860 {
861 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUnpackParametersForWebGL);
862 return false;
863 }
864 if (target == TextureTarget::_3D || target == TextureTarget::_2DArray)
865 {
866 GLint dataStoreHeight = unpack.imageHeight ? unpack.imageHeight : height;
867 if (unpack.skipRows + height > dataStoreHeight)
868 {
869 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUnpackParametersForWebGL);
870 return false;
871 }
872 }
873 }
874 }
875
876 return true;
877 }
878
ValidateES3TexImage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)879 bool ValidateES3TexImage2DParameters(const Context *context,
880 angle::EntryPoint entryPoint,
881 TextureTarget target,
882 GLint level,
883 GLenum internalformat,
884 bool isCompressed,
885 bool isSubImage,
886 GLint xoffset,
887 GLint yoffset,
888 GLint zoffset,
889 GLsizei width,
890 GLsizei height,
891 GLsizei depth,
892 GLint border,
893 GLenum format,
894 GLenum type,
895 GLsizei imageSize,
896 const void *pixels)
897 {
898 if (!ValidTexture2DDestinationTarget(context, target))
899 {
900 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
901 return false;
902 }
903
904 return ValidateES3TexImageParametersBase(
905 context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
906 yoffset, zoffset, width, height, depth, border, format, type, imageSize, pixels);
907 }
908
ValidateES3TexImage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)909 bool ValidateES3TexImage3DParameters(const Context *context,
910 angle::EntryPoint entryPoint,
911 TextureTarget target,
912 GLint level,
913 GLenum internalformat,
914 bool isCompressed,
915 bool isSubImage,
916 GLint xoffset,
917 GLint yoffset,
918 GLint zoffset,
919 GLsizei width,
920 GLsizei height,
921 GLsizei depth,
922 GLint border,
923 GLenum format,
924 GLenum type,
925 GLsizei bufSize,
926 const void *pixels)
927 {
928 if (!ValidTexture3DDestinationTarget(context, target))
929 {
930 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
931 return false;
932 }
933
934 return ValidateES3TexImageParametersBase(
935 context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
936 yoffset, zoffset, width, height, depth, border, format, type, bufSize, pixels);
937 }
938
939 struct EffectiveInternalFormatInfo
940 {
941 GLenum effectiveFormat;
942 GLenum destFormat;
943 GLuint minRedBits;
944 GLuint maxRedBits;
945 GLuint minGreenBits;
946 GLuint maxGreenBits;
947 GLuint minBlueBits;
948 GLuint maxBlueBits;
949 GLuint minAlphaBits;
950 GLuint maxAlphaBits;
951 };
952
QueryEffectiveFormatList(const InternalFormat & srcFormat,GLenum targetFormat,const EffectiveInternalFormatInfo * list,size_t size,GLenum * outEffectiveFormat)953 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
954 GLenum targetFormat,
955 const EffectiveInternalFormatInfo *list,
956 size_t size,
957 GLenum *outEffectiveFormat)
958 {
959 for (size_t curFormat = 0; curFormat < size; ++curFormat)
960 {
961 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
962 if ((formatInfo.destFormat == targetFormat) &&
963 (formatInfo.minRedBits <= srcFormat.redBits &&
964 formatInfo.maxRedBits >= srcFormat.redBits) &&
965 (formatInfo.minGreenBits <= srcFormat.greenBits &&
966 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
967 (formatInfo.minBlueBits <= srcFormat.blueBits &&
968 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
969 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
970 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
971 {
972 *outEffectiveFormat = formatInfo.effectiveFormat;
973 return true;
974 }
975 }
976
977 *outEffectiveFormat = GL_NONE;
978 return false;
979 }
980
GetSizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,GLenum * outEffectiveFormat)981 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
982 GLenum *outEffectiveFormat)
983 {
984 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
985 // Effective internal format coresponding to destination internal format and linear source
986 // buffer component sizes.
987 // | Source channel min/max sizes |
988 // Effective Internal Format | N/A | R | G | B | A |
989 // clang-format off
990 constexpr EffectiveInternalFormatInfo list[] = {
991 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
992 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
993 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
994 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
995 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
996 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
997 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
998 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
999 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
1000 };
1001 // clang-format on
1002
1003 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
1004 }
1005
GetUnsizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)1006 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
1007 const InternalFormat &destFormat,
1008 GLenum *outEffectiveFormat)
1009 {
1010 constexpr GLuint umax = UINT_MAX;
1011
1012 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
1013 // Effective internal format coresponding to destination internal format andlinear source buffer
1014 // component sizes.
1015 // | Source channel min/max sizes |
1016 // Effective Internal Format | Dest Format | R | G | B | A |
1017 // clang-format off
1018 constexpr EffectiveInternalFormatInfo list[] = {
1019 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
1020 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
1021 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
1022 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
1023 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
1024 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
1025 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
1026 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
1027 };
1028 // clang-format on
1029
1030 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
1031 outEffectiveFormat);
1032 }
1033
GetEffectiveInternalFormat(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)1034 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
1035 const InternalFormat &destFormat,
1036 GLenum *outEffectiveFormat)
1037 {
1038 if (destFormat.sized)
1039 {
1040 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
1041 }
1042 else
1043 {
1044 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
1045 }
1046 }
1047
EqualOrFirstZero(GLuint first,GLuint second)1048 static bool EqualOrFirstZero(GLuint first, GLuint second)
1049 {
1050 return first == 0 || first == second;
1051 }
1052
IsValidES3CopyTexImageCombination(const InternalFormat & textureFormatInfo,const InternalFormat & framebufferFormatInfo,FramebufferID readBufferHandle)1053 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
1054 const InternalFormat &framebufferFormatInfo,
1055 FramebufferID readBufferHandle)
1056 {
1057 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
1058 {
1059 return false;
1060 }
1061
1062 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
1063 // must both be signed, unsigned, or fixed point and both source and destinations
1064 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
1065 // conversion between fixed and floating point.
1066
1067 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
1068 (framebufferFormatInfo.colorEncoding == GL_SRGB))
1069 {
1070 return false;
1071 }
1072
1073 if (((textureFormatInfo.componentType == GL_INT) !=
1074 (framebufferFormatInfo.componentType == GL_INT)) ||
1075 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
1076 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
1077 {
1078 return false;
1079 }
1080
1081 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
1082 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
1083 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
1084 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
1085 {
1086 return false;
1087 }
1088
1089 if ((textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) !=
1090 (framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
1091 {
1092 return false;
1093 }
1094
1095 // Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that
1096 // the KHR dEQP tests enforce:
1097 //
1098 // Note that the above rules disallow matches where some components sizes are smaller and
1099 // others are larger (such as RGB10_A2).
1100 if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
1101 {
1102 return false;
1103 }
1104
1105 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
1106 // The effective internal format of the source buffer is determined with the following rules
1107 // applied in order:
1108 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
1109 // format then the effective internal format is the source buffer's sized internal format.
1110 // * If the source buffer is a texture that was created with an unsized base internal format,
1111 // then the effective internal format is the source image array's effective internal
1112 // format, as specified by table 3.12, which is determined from the <format> and <type>
1113 // that were used when the source image array was specified by TexImage*.
1114 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
1115 // where Destination Internal Format matches internalformat and where the [source channel
1116 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
1117 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
1118 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
1119 const InternalFormat *sourceEffectiveFormat = nullptr;
1120 if (readBufferHandle.value != 0)
1121 {
1122 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
1123 // renderbuffer
1124 if (framebufferFormatInfo.sized)
1125 {
1126 sourceEffectiveFormat = &framebufferFormatInfo;
1127 }
1128 else
1129 {
1130 // Renderbuffers cannot be created with an unsized internal format, so this must be an
1131 // unsized-format texture. We can use the same table we use when creating textures to
1132 // get its effective sized format.
1133 sourceEffectiveFormat =
1134 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
1135 }
1136 }
1137 else
1138 {
1139 // The effective internal format must be derived from the source framebuffer's channel
1140 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
1141 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
1142 {
1143 GLenum effectiveFormat;
1144 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
1145 &effectiveFormat))
1146 {
1147 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
1148 }
1149 else
1150 {
1151 return false;
1152 }
1153 }
1154 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
1155 {
1156 // SRGB buffers can only be copied to sized format destinations according to table 3.18
1157 if (textureFormatInfo.sized &&
1158 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
1159 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
1160 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
1161 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
1162 {
1163 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
1164 }
1165 else
1166 {
1167 return false;
1168 }
1169 }
1170 else
1171 {
1172 UNREACHABLE();
1173 return false;
1174 }
1175 }
1176
1177 if (textureFormatInfo.sized)
1178 {
1179 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
1180 // sized, component sizes of the source and destination formats must exactly match if the
1181 // destination format exists.
1182 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
1183 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
1184 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
1185 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
1186 {
1187 return false;
1188 }
1189 }
1190
1191 return true; // A conversion function exists, and no rule in the specification has precluded
1192 // conversion between these formats.
1193 }
1194
ValidateES3CopyTexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1195 bool ValidateES3CopyTexImageParametersBase(const Context *context,
1196 angle::EntryPoint entryPoint,
1197 TextureTarget target,
1198 GLint level,
1199 GLenum internalformat,
1200 bool isSubImage,
1201 GLint xoffset,
1202 GLint yoffset,
1203 GLint zoffset,
1204 GLint x,
1205 GLint y,
1206 GLsizei width,
1207 GLsizei height,
1208 GLint border)
1209 {
1210 Format textureFormat = Format::Invalid();
1211 if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1212 isSubImage, xoffset, yoffset, zoffset, x, y, width,
1213 height, border, &textureFormat))
1214 {
1215 return false;
1216 }
1217 ASSERT(textureFormat.valid() || !isSubImage);
1218
1219 const auto &state = context->getState();
1220 Framebuffer *framebuffer = state.getReadFramebuffer();
1221 FramebufferID readFramebufferID = framebuffer->id();
1222
1223 if (!ValidateFramebufferComplete(context, entryPoint, framebuffer))
1224 {
1225 return false;
1226 }
1227
1228 // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
1229 // resolved before copying
1230 if (!framebuffer->isDefault() &&
1231 !ValidateFramebufferNotMultisampled(context, entryPoint, framebuffer, true))
1232 {
1233 return false;
1234 }
1235
1236 const FramebufferAttachment *source = framebuffer->getReadColorAttachment();
1237
1238 // According to ES 3.x spec, if the internalformat of the texture
1239 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
1240 if (textureFormat.info->internalFormat == GL_RGB9_E5)
1241 {
1242 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
1243 return false;
1244 }
1245
1246 if (isSubImage)
1247 {
1248 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
1249 readFramebufferID))
1250 {
1251 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCopyCombination);
1252 return false;
1253 }
1254 }
1255 else
1256 {
1257 // Use format/type from the source FBO. (Might not be perfect for all cases?)
1258 const InternalFormat &framebufferFormat = *source->getFormat().info;
1259 const InternalFormat ©Format = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
1260 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
1261 {
1262 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCopyCombination);
1263 return false;
1264 }
1265 }
1266
1267 // If width or height is zero, it is a no-op. Return false without setting an error.
1268 return (width > 0 && height > 0);
1269 }
1270
ValidateES3CopyTexImage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1271 bool ValidateES3CopyTexImage2DParameters(const Context *context,
1272 angle::EntryPoint entryPoint,
1273 TextureTarget target,
1274 GLint level,
1275 GLenum internalformat,
1276 bool isSubImage,
1277 GLint xoffset,
1278 GLint yoffset,
1279 GLint zoffset,
1280 GLint x,
1281 GLint y,
1282 GLsizei width,
1283 GLsizei height,
1284 GLint border)
1285 {
1286 if (!ValidTexture2DDestinationTarget(context, target))
1287 {
1288 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1289 return false;
1290 }
1291
1292 return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1293 isSubImage, xoffset, yoffset, zoffset, x, y, width,
1294 height, border);
1295 }
1296
ValidateES3CopyTexImage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1297 bool ValidateES3CopyTexImage3DParameters(const Context *context,
1298 angle::EntryPoint entryPoint,
1299 TextureTarget target,
1300 GLint level,
1301 GLenum internalformat,
1302 bool isSubImage,
1303 GLint xoffset,
1304 GLint yoffset,
1305 GLint zoffset,
1306 GLint x,
1307 GLint y,
1308 GLsizei width,
1309 GLsizei height,
1310 GLint border)
1311 {
1312 if (!ValidTexture3DDestinationTarget(context, target))
1313 {
1314 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1315 return false;
1316 }
1317
1318 return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
1319 isSubImage, xoffset, yoffset, zoffset, x, y, width,
1320 height, border);
1321 }
1322
ValidateES3TexStorageParametersLevel(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth)1323 bool ValidateES3TexStorageParametersLevel(const Context *context,
1324 angle::EntryPoint entryPoint,
1325 TextureType target,
1326 GLsizei levels,
1327 GLsizei width,
1328 GLsizei height,
1329 GLsizei depth)
1330 {
1331 GLsizei maxDim = std::max(width, height);
1332 if (target != TextureType::_2DArray)
1333 {
1334 maxDim = std::max(maxDim, depth);
1335 }
1336
1337 if (levels > log2(maxDim) + 1)
1338 {
1339 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMipLevels);
1340 return false;
1341 }
1342
1343 return true;
1344 }
1345
ValidateES3TexStorageParametersExtent(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLsizei width,GLsizei height,GLsizei depth)1346 bool ValidateES3TexStorageParametersExtent(const Context *context,
1347 angle::EntryPoint entryPoint,
1348 TextureType target,
1349 GLsizei levels,
1350 GLsizei width,
1351 GLsizei height,
1352 GLsizei depth)
1353 {
1354 const Caps &caps = context->getCaps();
1355
1356 switch (target)
1357 {
1358 case TextureType::_2D:
1359 {
1360 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1361 {
1362 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1363 return false;
1364 }
1365 }
1366 break;
1367
1368 case TextureType::Rectangle:
1369 {
1370 if (levels != 1)
1371 {
1372 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevels);
1373 return false;
1374 }
1375
1376 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1377 {
1378 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1379 return false;
1380 }
1381 }
1382 break;
1383
1384 case TextureType::CubeMap:
1385 {
1386 if (width != height)
1387 {
1388 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1389 return false;
1390 }
1391
1392 if (width > caps.maxCubeMapTextureSize)
1393 {
1394 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1395 return false;
1396 }
1397 }
1398 break;
1399
1400 case TextureType::_3D:
1401 {
1402 if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
1403 depth > caps.max3DTextureSize)
1404 {
1405 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1406 return false;
1407 }
1408 }
1409 break;
1410
1411 case TextureType::_2DArray:
1412 {
1413 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize ||
1414 depth > caps.maxArrayTextureLayers)
1415 {
1416 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1417 return false;
1418 }
1419 }
1420 break;
1421
1422 case TextureType::CubeMapArray:
1423 {
1424 if (width != height)
1425 {
1426 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1427 return false;
1428 }
1429
1430 if (width > caps.maxCubeMapTextureSize)
1431 {
1432 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1433 return false;
1434 }
1435
1436 if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
1437 depth > caps.max3DTextureSize)
1438 {
1439 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
1440 return false;
1441 }
1442
1443 if (depth % 6 != 0)
1444 {
1445 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth);
1446 return false;
1447 }
1448 }
1449 break;
1450
1451 default:
1452 UNREACHABLE();
1453 return false;
1454 }
1455
1456 return true;
1457 }
1458
ValidateES3TexStorageParametersTexObject(const Context * context,angle::EntryPoint entryPoint,TextureType target)1459 bool ValidateES3TexStorageParametersTexObject(const Context *context,
1460 angle::EntryPoint entryPoint,
1461 TextureType target)
1462 {
1463 Texture *texture = context->getTextureByType(target);
1464 if (!texture || texture->id().value == 0)
1465 {
1466 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
1467 return false;
1468 }
1469
1470 if (texture->getImmutableFormat())
1471 {
1472 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
1473 return false;
1474 }
1475
1476 return true;
1477 }
1478
ValidateES3TexStorageParametersFormat(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1479 bool ValidateES3TexStorageParametersFormat(const Context *context,
1480 angle::EntryPoint entryPoint,
1481 TextureType target,
1482 GLsizei levels,
1483 GLenum internalformat,
1484 GLsizei width,
1485 GLsizei height,
1486 GLsizei depth)
1487 {
1488 // From ANGLE_texture_external_yuv_sampling:
1489 // Texture target can only be TEXTURE_2D, there is no mipmap support
1490 if (gl::IsYuvFormat(internalformat))
1491 {
1492 if (!context->getExtensions().yuvInternalFormatANGLE)
1493 {
1494 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1495 return false;
1496 }
1497
1498 if (target != TextureType::_2D)
1499 {
1500 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1501 return false;
1502 }
1503
1504 if (levels != 1)
1505 {
1506 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
1507 return false;
1508 }
1509 }
1510
1511 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1512 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1513 {
1514 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1515 return false;
1516 }
1517
1518 if (!formatInfo.sized)
1519 {
1520 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidInternalFormat, internalformat);
1521 return false;
1522 }
1523
1524 if (formatInfo.compressed)
1525 {
1526 if (target == TextureType::Rectangle)
1527 {
1528 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRectangleTextureCompressed);
1529 return false;
1530 }
1531
1532 if (target == TextureType::_2DArray)
1533 {
1534 if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
1535 formatInfo.internalFormat))
1536 {
1537 // Error already generated.
1538 return false;
1539 }
1540 }
1541
1542 if (target == TextureType::_3D)
1543 {
1544 if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint,
1545 formatInfo.internalFormat))
1546 {
1547 // Error already generated.
1548 return false;
1549 }
1550 }
1551
1552 if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
1553 {
1554 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
1555 return false;
1556 }
1557 }
1558
1559 return true;
1560 }
1561
ValidateES3TexStorageParametersBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1562 bool ValidateES3TexStorageParametersBase(const Context *context,
1563 angle::EntryPoint entryPoint,
1564 TextureType target,
1565 GLsizei levels,
1566 GLenum internalformat,
1567 GLsizei width,
1568 GLsizei height,
1569 GLsizei depth)
1570 {
1571 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1572 {
1573 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
1574 return false;
1575 }
1576
1577 if (!ValidateES3TexStorageParametersLevel(context, entryPoint, target, levels, width, height,
1578 depth))
1579 {
1580 // Error already generated.
1581 return false;
1582 }
1583
1584 if (!ValidateES3TexStorageParametersExtent(context, entryPoint, target, levels, width, height,
1585 depth))
1586 {
1587 // Error already generated.
1588 return false;
1589 }
1590
1591 if (!ValidateES3TexStorageParametersTexObject(context, entryPoint, target))
1592 {
1593 // Error already generated.
1594 return false;
1595 }
1596
1597 if (!ValidateES3TexStorageParametersFormat(context, entryPoint, target, levels, internalformat,
1598 width, height, depth))
1599 {
1600 // Error already generated.
1601 return false;
1602 }
1603
1604 return true;
1605 }
1606
ValidateES3TexStorage2DParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1607 bool ValidateES3TexStorage2DParameters(const Context *context,
1608 angle::EntryPoint entryPoint,
1609 TextureType target,
1610 GLsizei levels,
1611 GLenum internalformat,
1612 GLsizei width,
1613 GLsizei height,
1614 GLsizei depth)
1615 {
1616 if (!ValidTexture2DTarget(context, target))
1617 {
1618 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1619 return false;
1620 }
1621
1622 return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
1623 width, height, depth);
1624 }
1625
ValidateES3TexStorage3DParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1626 bool ValidateES3TexStorage3DParameters(const Context *context,
1627 angle::EntryPoint entryPoint,
1628 TextureType target,
1629 GLsizei levels,
1630 GLenum internalformat,
1631 GLsizei width,
1632 GLsizei height,
1633 GLsizei depth)
1634 {
1635 if (!ValidTexture3DTarget(context, target))
1636 {
1637 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
1638 return false;
1639 }
1640
1641 return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
1642 width, height, depth);
1643 }
1644
ValidateBeginQuery(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)1645 bool ValidateBeginQuery(const Context *context,
1646 angle::EntryPoint entryPoint,
1647 QueryType target,
1648 QueryID id)
1649 {
1650 if (context->getClientMajorVersion() < 3)
1651 {
1652 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1653 return false;
1654 }
1655
1656 return ValidateBeginQueryBase(context, entryPoint, target, id);
1657 }
1658
ValidateEndQuery(const Context * context,angle::EntryPoint entryPoint,QueryType target)1659 bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType target)
1660 {
1661 if (context->getClientMajorVersion() < 3)
1662 {
1663 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1664 return false;
1665 }
1666
1667 return ValidateEndQueryBase(context, entryPoint, target);
1668 }
1669
ValidateGetQueryiv(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,const GLint * params)1670 bool ValidateGetQueryiv(const Context *context,
1671 angle::EntryPoint entryPoint,
1672 QueryType target,
1673 GLenum pname,
1674 const GLint *params)
1675 {
1676 if (context->getClientMajorVersion() < 3)
1677 {
1678 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1679 return false;
1680 }
1681
1682 return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
1683 }
1684
ValidateGetQueryObjectuiv(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLuint * params)1685 bool ValidateGetQueryObjectuiv(const Context *context,
1686 angle::EntryPoint entryPoint,
1687 QueryID id,
1688 GLenum pname,
1689 const GLuint *params)
1690 {
1691 if (context->getClientMajorVersion() < 3)
1692 {
1693 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1694 return false;
1695 }
1696
1697 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
1698 }
1699
ValidateFramebufferTextureLayer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint layer)1700 bool ValidateFramebufferTextureLayer(const Context *context,
1701 angle::EntryPoint entryPoint,
1702 GLenum target,
1703 GLenum attachment,
1704 TextureID texture,
1705 GLint level,
1706 GLint layer)
1707 {
1708 if (context->getClientMajorVersion() < 3)
1709 {
1710 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1711 return false;
1712 }
1713
1714 if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
1715 {
1716 return false;
1717 }
1718
1719 const Caps &caps = context->getCaps();
1720 if (texture.value != 0)
1721 {
1722 if (layer < 0)
1723 {
1724 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLayer);
1725 return false;
1726 }
1727
1728 Texture *tex = context->getTexture(texture);
1729 ASSERT(tex);
1730
1731 switch (tex->getType())
1732 {
1733 case TextureType::_2DArray:
1734 {
1735 if (level > log2(caps.max2DTextureSize))
1736 {
1737 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1738 return false;
1739 }
1740
1741 if (layer >= caps.maxArrayTextureLayers)
1742 {
1743 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1744 return false;
1745 }
1746 }
1747 break;
1748
1749 case TextureType::_3D:
1750 {
1751 if (level > log2(caps.max3DTextureSize))
1752 {
1753 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1754 return false;
1755 }
1756
1757 if (layer >= caps.max3DTextureSize)
1758 {
1759 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1760 return false;
1761 }
1762 }
1763 break;
1764
1765 case TextureType::_2DMultisampleArray:
1766 {
1767 if (level != 0)
1768 {
1769 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1770 return false;
1771 }
1772
1773 if (layer >= caps.maxArrayTextureLayers)
1774 {
1775 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1776 return false;
1777 }
1778 }
1779 break;
1780
1781 case TextureType::CubeMap:
1782 {
1783 if (level > log2(caps.maxCubeMapTextureSize))
1784 {
1785 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1786 return false;
1787 }
1788
1789 if (layer >= static_cast<GLint>(kCubeFaceCount))
1790 {
1791 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1792 return false;
1793 }
1794 }
1795 break;
1796
1797 case TextureType::CubeMapArray:
1798 {
1799 if (level > log2(caps.maxCubeMapTextureSize))
1800 {
1801 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1802 return false;
1803 }
1804
1805 if (layer >= caps.maxArrayTextureLayers)
1806 {
1807 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1808 return false;
1809 }
1810 }
1811 break;
1812
1813 default:
1814 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1815 kFramebufferTextureLayerIncorrectTextureType);
1816 return false;
1817 }
1818
1819 const auto &format = tex->getFormat(TextureTypeToTarget(tex->getType(), layer), level);
1820 if (format.info->compressed)
1821 {
1822 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
1823 return false;
1824 }
1825 }
1826
1827 return true;
1828 }
1829
ValidateInvalidateFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments)1830 bool ValidateInvalidateFramebuffer(const Context *context,
1831 angle::EntryPoint entryPoint,
1832 GLenum target,
1833 GLsizei numAttachments,
1834 const GLenum *attachments)
1835 {
1836 if (context->getClientMajorVersion() < 3)
1837 {
1838 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1839 return false;
1840 }
1841
1842 bool defaultFramebuffer = false;
1843
1844 switch (target)
1845 {
1846 case GL_DRAW_FRAMEBUFFER:
1847 case GL_FRAMEBUFFER:
1848 defaultFramebuffer = context->getState().getDrawFramebuffer()->isDefault();
1849 break;
1850 case GL_READ_FRAMEBUFFER:
1851 defaultFramebuffer = context->getState().getReadFramebuffer()->isDefault();
1852 break;
1853 default:
1854 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1855 return false;
1856 }
1857
1858 return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
1859 defaultFramebuffer);
1860 }
1861
ValidateInvalidateSubFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)1862 bool ValidateInvalidateSubFramebuffer(const Context *context,
1863 angle::EntryPoint entryPoint,
1864 GLenum target,
1865 GLsizei numAttachments,
1866 const GLenum *attachments,
1867 GLint x,
1868 GLint y,
1869 GLsizei width,
1870 GLsizei height)
1871 {
1872 if (width < 0 || height < 0)
1873 {
1874 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
1875 return false;
1876 }
1877
1878 return ValidateInvalidateFramebuffer(context, entryPoint, target, numAttachments, attachments);
1879 }
1880
ValidateClearBuffer(const Context * context,angle::EntryPoint entryPoint)1881 bool ValidateClearBuffer(const Context *context, angle::EntryPoint entryPoint)
1882 {
1883 if (context->getClientMajorVersion() < 3)
1884 {
1885 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1886 return false;
1887 }
1888
1889 Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
1890 if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer))
1891 {
1892 return false;
1893 }
1894
1895 // The QCOM_framebuffer_foveated spec:
1896 if (drawFramebuffer->isFoveationEnabled())
1897 {
1898 // INVALID_OPERATION is generated by any API call which causes a framebuffer
1899 // attachment to be written to if the framebuffer attachments have changed for
1900 // a foveated fbo.
1901 if (drawFramebuffer->hasAnyAttachmentChanged())
1902 {
1903 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFramebufferFoveationAttachmentChanged);
1904 return false;
1905 }
1906 }
1907
1908 return true;
1909 }
1910
ValidateDrawRangeElements(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,DrawElementsType type,const void * indices)1911 bool ValidateDrawRangeElements(const Context *context,
1912 angle::EntryPoint entryPoint,
1913 PrimitiveMode mode,
1914 GLuint start,
1915 GLuint end,
1916 GLsizei count,
1917 DrawElementsType type,
1918 const void *indices)
1919 {
1920 if (context->getClientMajorVersion() < 3)
1921 {
1922 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1923 return false;
1924 }
1925
1926 if (end < start)
1927 {
1928 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidElementRange);
1929 return false;
1930 }
1931
1932 if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1))
1933 {
1934 return false;
1935 }
1936
1937 // Skip range checks for no-op calls.
1938 if (count <= 0)
1939 {
1940 return true;
1941 }
1942
1943 return true;
1944 }
1945
ValidateGetUniformuiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,const GLuint * params)1946 bool ValidateGetUniformuiv(const Context *context,
1947 angle::EntryPoint entryPoint,
1948 ShaderProgramID program,
1949 UniformLocation location,
1950 const GLuint *params)
1951 {
1952 if (context->getClientMajorVersion() < 3)
1953 {
1954 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1955 return false;
1956 }
1957
1958 return ValidateGetUniformBase(context, entryPoint, program, location);
1959 }
1960
ValidateReadBuffer(const Context * context,angle::EntryPoint entryPoint,GLenum src)1961 bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src)
1962 {
1963 if (context->getClientMajorVersion() < 3)
1964 {
1965 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
1966 return false;
1967 }
1968
1969 const Framebuffer *readFBO = context->getState().getReadFramebuffer();
1970
1971 if (readFBO == nullptr)
1972 {
1973 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoReadFramebuffer);
1974 return false;
1975 }
1976
1977 if (src == GL_NONE)
1978 {
1979 return true;
1980 }
1981
1982 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
1983 {
1984 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidReadBuffer);
1985 return false;
1986 }
1987
1988 if (readFBO->isDefault())
1989 {
1990 if (src != GL_BACK)
1991 {
1992 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDefaultReadBuffer);
1993 return false;
1994 }
1995 }
1996 else
1997 {
1998 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1999
2000 if (drawBuffer >= static_cast<GLuint>(context->getCaps().maxColorAttachments))
2001 {
2002 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
2003 return false;
2004 }
2005 }
2006
2007 return true;
2008 }
2009
ValidateCompressedTexImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)2010 bool ValidateCompressedTexImage3D(const Context *context,
2011 angle::EntryPoint entryPoint,
2012 TextureTarget target,
2013 GLint level,
2014 GLenum internalformat,
2015 GLsizei width,
2016 GLsizei height,
2017 GLsizei depth,
2018 GLint border,
2019 GLsizei imageSize,
2020 const void *data)
2021 {
2022 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2023 {
2024 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2025 return false;
2026 }
2027
2028 if (!ValidTextureTarget(context, TextureTargetToType(target)))
2029 {
2030 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2031 return false;
2032 }
2033
2034 // Validate image size
2035 if (!ValidImageSizeParameters(context, entryPoint, TextureTargetToType(target), level, width,
2036 height, depth, false))
2037 {
2038 // Error already generated.
2039 return false;
2040 }
2041
2042 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
2043 if (!formatInfo.compressed)
2044 {
2045 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidCompressedFormat);
2046 return false;
2047 }
2048
2049 GLuint blockSize = 0;
2050 if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
2051 {
2052 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
2053 return false;
2054 }
2055
2056 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2057 {
2058 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2059 return false;
2060 }
2061
2062 // 3D texture target validation
2063 if (target != TextureTarget::_3D && target != TextureTarget::_2DArray)
2064 {
2065 if (context->getClientVersion() < ES_3_2 || target != TextureTarget::CubeMapArray)
2066 {
2067 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2068 return false;
2069 }
2070 }
2071
2072 // validateES3TexImageFormat sets the error code if there is an error
2073 if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat, true,
2074 false, 0, 0, 0, width, height, depth, border, GL_NONE,
2075 GL_NONE, -1, data))
2076 {
2077 return false;
2078 }
2079
2080 return true;
2081 }
2082
ValidateCompressedTexImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)2083 bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
2084 angle::EntryPoint entryPoint,
2085 TextureTarget target,
2086 GLint level,
2087 GLenum internalformat,
2088 GLsizei width,
2089 GLsizei height,
2090 GLsizei depth,
2091 GLint border,
2092 GLsizei imageSize,
2093 GLsizei dataSize,
2094 const void *data)
2095 {
2096 if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
2097 {
2098 return false;
2099 }
2100
2101 return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
2102 height, depth, border, imageSize, data);
2103 }
2104
ValidateBindVertexArray(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)2105 bool ValidateBindVertexArray(const Context *context,
2106 angle::EntryPoint entryPoint,
2107 VertexArrayID array)
2108 {
2109 if (context->getClientMajorVersion() < 3)
2110 {
2111 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2112 return false;
2113 }
2114
2115 return ValidateBindVertexArrayBase(context, entryPoint, array);
2116 }
2117
ValidateIsVertexArray(const Context * context,angle::EntryPoint entryPoint,VertexArrayID array)2118 bool ValidateIsVertexArray(const Context *context,
2119 angle::EntryPoint entryPoint,
2120 VertexArrayID array)
2121 {
2122 if (context->getClientMajorVersion() < 3)
2123 {
2124 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2125 return false;
2126 }
2127
2128 return true;
2129 }
2130
ValidateBindBufferCommon(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)2131 static bool ValidateBindBufferCommon(const Context *context,
2132 angle::EntryPoint entryPoint,
2133 BufferBinding target,
2134 GLuint index,
2135 BufferID buffer,
2136 GLintptr offset,
2137 GLsizeiptr size)
2138 {
2139 if (context->getClientMajorVersion() < 3)
2140 {
2141 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2142 return false;
2143 }
2144
2145 if (buffer.value != 0 && offset < 0)
2146 {
2147 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
2148 return false;
2149 }
2150
2151 if (!context->getState().isBindGeneratesResourceEnabled() &&
2152 !context->isBufferGenerated(buffer))
2153 {
2154 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
2155 return false;
2156 }
2157
2158 const Caps &caps = context->getCaps();
2159 switch (target)
2160 {
2161 case BufferBinding::TransformFeedback:
2162 {
2163 if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
2164 {
2165 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
2166 kIndexExceedsTransformFeedbackBufferBindings);
2167 return false;
2168 }
2169 if (buffer.value != 0 && ((offset % 4) != 0 || (size % 4) != 0))
2170 {
2171 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetAndSizeAlignment);
2172 return false;
2173 }
2174
2175 if (context->getState().isTransformFeedbackActive())
2176 {
2177 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackTargetActive);
2178 return false;
2179 }
2180 break;
2181 }
2182 case BufferBinding::Uniform:
2183 {
2184 if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
2185 {
2186 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
2187 return false;
2188 }
2189
2190 ASSERT(caps.uniformBufferOffsetAlignment);
2191 if (buffer.value != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
2192 {
2193 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformBufferOffsetAlignment);
2194 return false;
2195 }
2196 break;
2197 }
2198 case BufferBinding::AtomicCounter:
2199 {
2200 if (context->getClientVersion() < ES_3_1)
2201 {
2202 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
2203 return false;
2204 }
2205 if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
2206 {
2207 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
2208 kIndexExceedsMaxAtomicCounterBufferBindings);
2209 return false;
2210 }
2211 if (buffer.value != 0 && (offset % 4) != 0)
2212 {
2213 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetAlignment);
2214 return false;
2215 }
2216 break;
2217 }
2218 case BufferBinding::ShaderStorage:
2219 {
2220 if (context->getClientVersion() < ES_3_1)
2221 {
2222 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
2223 return false;
2224 }
2225 if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
2226 {
2227 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
2228 return false;
2229 }
2230 ASSERT(caps.shaderStorageBufferOffsetAlignment);
2231 if (buffer.value != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
2232 {
2233 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kShaderStorageBufferOffsetAlignment);
2234 return false;
2235 }
2236 break;
2237 }
2238 case BufferBinding::Texture:
2239 {
2240 if (!context->getExtensions().textureBufferAny())
2241 {
2242 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
2243 return false;
2244 }
2245 if (index != 0)
2246 {
2247 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
2248 return false;
2249 }
2250 if (buffer.value != 0 && (offset % caps.textureBufferOffsetAlignment) != 0)
2251 {
2252 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureBufferOffsetAlignment);
2253 return false;
2254 }
2255 break;
2256 }
2257 case BufferBinding::InvalidEnum:
2258 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid);
2259 return false;
2260 default:
2261 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(target));
2262 return false;
2263 }
2264
2265 return true;
2266 }
2267
ValidateBindBufferBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer)2268 bool ValidateBindBufferBase(const Context *context,
2269 angle::EntryPoint entryPoint,
2270 BufferBinding target,
2271 GLuint index,
2272 BufferID buffer)
2273 {
2274 return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, 0, 0);
2275 }
2276
ValidateBindBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)2277 bool ValidateBindBufferRange(const Context *context,
2278 angle::EntryPoint entryPoint,
2279 BufferBinding target,
2280 GLuint index,
2281 BufferID buffer,
2282 GLintptr offset,
2283 GLsizeiptr size)
2284 {
2285 if (buffer.value != 0 && size <= 0)
2286 {
2287 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBindBufferSize);
2288 return false;
2289 }
2290 return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, offset, size);
2291 }
2292
ValidateProgramBinary(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLsizei length)2293 bool ValidateProgramBinary(const Context *context,
2294 angle::EntryPoint entryPoint,
2295 ShaderProgramID program,
2296 GLenum binaryFormat,
2297 const void *binary,
2298 GLsizei length)
2299 {
2300 if (context->getClientMajorVersion() < 3)
2301 {
2302 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2303 return false;
2304 }
2305
2306 return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
2307 }
2308
ValidateGetProgramBinary(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)2309 bool ValidateGetProgramBinary(const Context *context,
2310 angle::EntryPoint entryPoint,
2311 ShaderProgramID program,
2312 GLsizei bufSize,
2313 const GLsizei *length,
2314 const GLenum *binaryFormat,
2315 const void *binary)
2316 {
2317 if (context->getClientMajorVersion() < 3)
2318 {
2319 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2320 return false;
2321 }
2322
2323 return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
2324 binary);
2325 }
2326
ValidateProgramParameteriBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLint value)2327 bool ValidateProgramParameteriBase(const Context *context,
2328 angle::EntryPoint entryPoint,
2329 ShaderProgramID program,
2330 GLenum pname,
2331 GLint value)
2332 {
2333 if (GetValidProgram(context, entryPoint, program) == nullptr)
2334 {
2335 return false;
2336 }
2337
2338 switch (pname)
2339 {
2340 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
2341 if (value != GL_FALSE && value != GL_TRUE)
2342 {
2343 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBooleanValue);
2344 return false;
2345 }
2346 break;
2347
2348 case GL_PROGRAM_SEPARABLE:
2349 if (context->getClientVersion() < ES_3_1)
2350 {
2351 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES31Required);
2352 return false;
2353 }
2354
2355 if (value != GL_FALSE && value != GL_TRUE)
2356 {
2357 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBooleanValue);
2358 return false;
2359 }
2360 break;
2361
2362 default:
2363 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2364 return false;
2365 }
2366
2367 return true;
2368 }
2369
ValidateProgramParameteri(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLint value)2370 bool ValidateProgramParameteri(const Context *context,
2371 angle::EntryPoint entryPoint,
2372 ShaderProgramID program,
2373 GLenum pname,
2374 GLint value)
2375 {
2376 if (context->getClientMajorVersion() < 3)
2377 {
2378 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2379 return false;
2380 }
2381
2382 return ValidateProgramParameteriBase(context, entryPoint, program, pname, value);
2383 }
2384
ValidateBlitFramebuffer(const Context * context,angle::EntryPoint entryPoint,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)2385 bool ValidateBlitFramebuffer(const Context *context,
2386 angle::EntryPoint entryPoint,
2387 GLint srcX0,
2388 GLint srcY0,
2389 GLint srcX1,
2390 GLint srcY1,
2391 GLint dstX0,
2392 GLint dstY0,
2393 GLint dstX1,
2394 GLint dstY1,
2395 GLbitfield mask,
2396 GLenum filter)
2397 {
2398 if (context->getClientMajorVersion() < 3 && !context->getExtensions().framebufferBlitNV)
2399 {
2400 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2401 return false;
2402 }
2403
2404 return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
2405 dstY0, dstX1, dstY1, mask, filter);
2406 }
2407
ValidateClearBufferiv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLint * value)2408 bool ValidateClearBufferiv(const Context *context,
2409 angle::EntryPoint entryPoint,
2410 GLenum buffer,
2411 GLint drawbuffer,
2412 const GLint *value)
2413 {
2414 switch (buffer)
2415 {
2416 case GL_COLOR:
2417 if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2418 context->getMutableErrorSetForValidation(),
2419 entryPoint, drawbuffer, "drawbuffer"))
2420 {
2421 return false;
2422 }
2423 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2424 {
2425 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2426 return false;
2427 }
2428 if (static_cast<size_t>(drawbuffer) >=
2429 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2430 {
2431 // Clearing a non-existent draw buffer is a no-op.
2432 break;
2433 }
2434 if (context->getExtensions().webglCompatibilityANGLE)
2435 {
2436 const gl::ComponentTypeMask mask =
2437 context->getState().getDrawFramebuffer()->getDrawBufferTypeMask();
2438 if (IsComponentTypeFloatOrUnsignedInt(mask, drawbuffer))
2439 {
2440 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoDefinedClearConversion);
2441 return false;
2442 }
2443 }
2444 if (context->getExtensions().renderSharedExponentQCOM)
2445 {
2446 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2447 {
2448 return false;
2449 }
2450 }
2451 break;
2452
2453 case GL_STENCIL:
2454 if (drawbuffer != 0)
2455 {
2456 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2457 return false;
2458 }
2459 break;
2460
2461 default:
2462 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2463 return false;
2464 }
2465
2466 return ValidateClearBuffer(context, entryPoint);
2467 }
2468
ValidateClearBufferuiv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLuint * value)2469 bool ValidateClearBufferuiv(const Context *context,
2470 angle::EntryPoint entryPoint,
2471 GLenum buffer,
2472 GLint drawbuffer,
2473 const GLuint *value)
2474 {
2475 switch (buffer)
2476 {
2477 case GL_COLOR:
2478 if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2479 context->getMutableErrorSetForValidation(),
2480 entryPoint, drawbuffer, "drawbuffer"))
2481 {
2482 return false;
2483 }
2484 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2485 {
2486 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2487 return false;
2488 }
2489 if (static_cast<size_t>(drawbuffer) >=
2490 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2491 {
2492 // Clearing a non-existent draw buffer is a no-op.
2493 break;
2494 }
2495 if (context->getExtensions().webglCompatibilityANGLE)
2496 {
2497 const gl::ComponentTypeMask mask =
2498 context->getState().getDrawFramebuffer()->getDrawBufferTypeMask();
2499 if (IsComponentTypeFloatOrInt(mask, drawbuffer))
2500 {
2501 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoDefinedClearConversion);
2502 return false;
2503 }
2504 }
2505 if (context->getExtensions().renderSharedExponentQCOM)
2506 {
2507 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2508 {
2509 return false;
2510 }
2511 }
2512 break;
2513
2514 default:
2515 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2516 return false;
2517 }
2518
2519 return ValidateClearBuffer(context, entryPoint);
2520 }
2521
ValidateClearBufferfv(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,const GLfloat * value)2522 bool ValidateClearBufferfv(const Context *context,
2523 angle::EntryPoint entryPoint,
2524 GLenum buffer,
2525 GLint drawbuffer,
2526 const GLfloat *value)
2527 {
2528 switch (buffer)
2529 {
2530 case GL_COLOR:
2531 if (!ValidateDrawBufferIndexIfActivePLS(context->getPrivateState(),
2532 context->getMutableErrorSetForValidation(),
2533 entryPoint, drawbuffer, "drawbuffer"))
2534 {
2535 return false;
2536 }
2537 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2538 {
2539 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2540 return false;
2541 }
2542 if (static_cast<size_t>(drawbuffer) >=
2543 context->getState().getDrawFramebuffer()->getDrawbufferStateCount())
2544 {
2545 // Clearing a non-existent draw buffer is a no-op.
2546 break;
2547 }
2548 if (context->getExtensions().webglCompatibilityANGLE)
2549 {
2550 const gl::ComponentTypeMask mask =
2551 context->getState().getDrawFramebuffer()->getDrawBufferTypeMask();
2552 if (IsComponentTypeIntOrUnsignedInt(mask, drawbuffer))
2553 {
2554 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoDefinedClearConversion);
2555 return false;
2556 }
2557 }
2558 if (context->getExtensions().renderSharedExponentQCOM)
2559 {
2560 if (!ValidateColorMaskForSharedExponentColorBuffer(context, entryPoint, drawbuffer))
2561 {
2562 return false;
2563 }
2564 }
2565 break;
2566
2567 case GL_DEPTH:
2568 if (drawbuffer != 0)
2569 {
2570 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2571 return false;
2572 }
2573 break;
2574
2575 default:
2576 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2577 return false;
2578 }
2579
2580 return ValidateClearBuffer(context, entryPoint);
2581 }
2582
ValidateClearBufferfi(const Context * context,angle::EntryPoint entryPoint,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)2583 bool ValidateClearBufferfi(const Context *context,
2584 angle::EntryPoint entryPoint,
2585 GLenum buffer,
2586 GLint drawbuffer,
2587 GLfloat depth,
2588 GLint stencil)
2589 {
2590 switch (buffer)
2591 {
2592 case GL_DEPTH_STENCIL:
2593 if (drawbuffer != 0)
2594 {
2595 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2596 return false;
2597 }
2598 break;
2599
2600 default:
2601 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, buffer);
2602 return false;
2603 }
2604
2605 return ValidateClearBuffer(context, entryPoint);
2606 }
2607
ValidateDrawBuffers(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const GLenum * bufs)2608 bool ValidateDrawBuffers(const Context *context,
2609 angle::EntryPoint entryPoint,
2610 GLsizei n,
2611 const GLenum *bufs)
2612 {
2613 if (context->getClientMajorVersion() < 3)
2614 {
2615 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2616 return false;
2617 }
2618
2619 return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
2620 }
2621
ValidateCopyTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)2622 bool ValidateCopyTexSubImage3D(const Context *context,
2623 angle::EntryPoint entryPoint,
2624 TextureTarget target,
2625 GLint level,
2626 GLint xoffset,
2627 GLint yoffset,
2628 GLint zoffset,
2629 GLint x,
2630 GLint y,
2631 GLsizei width,
2632 GLsizei height)
2633 {
2634 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2635 {
2636 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2637 return false;
2638 }
2639
2640 return ValidateES3CopyTexImage3DParameters(context, entryPoint, target, level, GL_NONE, true,
2641 xoffset, yoffset, zoffset, x, y, width, height, 0);
2642 }
2643
ValidateCopyTexture3DANGLE(const Context * context,angle::EntryPoint entryPoint,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2644 bool ValidateCopyTexture3DANGLE(const Context *context,
2645 angle::EntryPoint entryPoint,
2646 TextureID sourceId,
2647 GLint sourceLevel,
2648 TextureTarget destTarget,
2649 TextureID destId,
2650 GLint destLevel,
2651 GLint internalFormat,
2652 GLenum destType,
2653 GLboolean unpackFlipY,
2654 GLboolean unpackPremultiplyAlpha,
2655 GLboolean unpackUnmultiplyAlpha)
2656 {
2657 const Texture *source = context->getTexture(sourceId);
2658 if (source == nullptr)
2659 {
2660 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
2661 return false;
2662 }
2663
2664 TextureType sourceType = source->getType();
2665 ASSERT(sourceType != TextureType::CubeMap);
2666 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2667 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2668
2669 const Texture *dest = context->getTexture(destId);
2670 if (dest == nullptr)
2671 {
2672 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
2673 return false;
2674 }
2675
2676 if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
2677 sourceFormat.info->internalFormat, dest, destLevel,
2678 internalFormat, destTarget))
2679 {
2680 return false;
2681 }
2682
2683 if (!ValidMipLevel(context, source->getType(), sourceLevel))
2684 {
2685 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
2686 return false;
2687 }
2688
2689 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
2690 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
2691 if (sourceWidth == 0 || sourceHeight == 0)
2692 {
2693 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureSize);
2694 return false;
2695 }
2696
2697 if (dest->getImmutableFormat())
2698 {
2699 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDestinationImmutable);
2700 return false;
2701 }
2702
2703 return true;
2704 }
2705
ValidateCopySubTexture3DANGLE(const Context * context,angle::EntryPoint entryPoint,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLint z,GLsizei width,GLsizei height,GLsizei depth,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2706 bool ValidateCopySubTexture3DANGLE(const Context *context,
2707 angle::EntryPoint entryPoint,
2708 TextureID sourceId,
2709 GLint sourceLevel,
2710 TextureTarget destTarget,
2711 TextureID destId,
2712 GLint destLevel,
2713 GLint xoffset,
2714 GLint yoffset,
2715 GLint zoffset,
2716 GLint x,
2717 GLint y,
2718 GLint z,
2719 GLsizei width,
2720 GLsizei height,
2721 GLsizei depth,
2722 GLboolean unpackFlipY,
2723 GLboolean unpackPremultiplyAlpha,
2724 GLboolean unpackUnmultiplyAlpha)
2725 {
2726 const Texture *source = context->getTexture(sourceId);
2727 if (source == nullptr)
2728 {
2729 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
2730 return false;
2731 }
2732
2733 TextureType sourceType = source->getType();
2734 ASSERT(sourceType != TextureType::CubeMap);
2735 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2736 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2737
2738 const Texture *dest = context->getTexture(destId);
2739 if (dest == nullptr)
2740 {
2741 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
2742 return false;
2743 }
2744
2745 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
2746
2747 if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
2748 sourceFormat.info->internalFormat, dest, destLevel,
2749 destFormat.internalFormat, destTarget))
2750 {
2751 return false;
2752 }
2753
2754 if (x < 0 || y < 0 || z < 0)
2755 {
2756 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeXYZ);
2757 return false;
2758 }
2759
2760 if (width < 0 || height < 0 || depth < 0)
2761 {
2762 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeHeightWidthDepth);
2763 return false;
2764 }
2765
2766 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
2767 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
2768 static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
2769 {
2770 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
2771 return false;
2772 }
2773
2774 if (TextureTargetToType(destTarget) != dest->getType())
2775 {
2776 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTextureType);
2777 return false;
2778 }
2779
2780 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2781 {
2782 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
2783 return false;
2784 }
2785
2786 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
2787 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
2788 static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
2789 {
2790 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDestinationTextureTooSmall);
2791 return false;
2792 }
2793
2794 return true;
2795 }
2796
ValidateTexImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)2797 bool ValidateTexImage3D(const Context *context,
2798 angle::EntryPoint entryPoint,
2799 TextureTarget target,
2800 GLint level,
2801 GLint internalformat,
2802 GLsizei width,
2803 GLsizei height,
2804 GLsizei depth,
2805 GLint border,
2806 GLenum format,
2807 GLenum type,
2808 const void *pixels)
2809 {
2810 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2811 {
2812 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2813 return false;
2814 }
2815
2816 return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
2817 false, false, 0, 0, 0, width, height, depth, border,
2818 format, type, -1, pixels);
2819 }
2820
ValidateTexImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2821 bool ValidateTexImage3DRobustANGLE(const Context *context,
2822 angle::EntryPoint entryPoint,
2823 TextureTarget target,
2824 GLint level,
2825 GLint internalformat,
2826 GLsizei width,
2827 GLsizei height,
2828 GLsizei depth,
2829 GLint border,
2830 GLenum format,
2831 GLenum type,
2832 GLsizei bufSize,
2833 const void *pixels)
2834 {
2835 if (context->getClientMajorVersion() < 3)
2836 {
2837 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2838 return false;
2839 }
2840
2841 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2842 {
2843 return false;
2844 }
2845
2846 return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
2847 false, false, 0, 0, 0, width, height, depth, border,
2848 format, type, bufSize, pixels);
2849 }
2850
ValidateTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2851 bool ValidateTexSubImage3D(const Context *context,
2852 angle::EntryPoint entryPoint,
2853 TextureTarget target,
2854 GLint level,
2855 GLint xoffset,
2856 GLint yoffset,
2857 GLint zoffset,
2858 GLsizei width,
2859 GLsizei height,
2860 GLsizei depth,
2861 GLenum format,
2862 GLenum type,
2863 const void *pixels)
2864 {
2865 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2866 {
2867 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2868 return false;
2869 }
2870
2871 return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
2872 xoffset, yoffset, zoffset, width, height, depth, 0,
2873 format, type, -1, pixels);
2874 }
2875
ValidateTexSubImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2876 bool ValidateTexSubImage3DRobustANGLE(const Context *context,
2877 angle::EntryPoint entryPoint,
2878 TextureTarget target,
2879 GLint level,
2880 GLint xoffset,
2881 GLint yoffset,
2882 GLint zoffset,
2883 GLsizei width,
2884 GLsizei height,
2885 GLsizei depth,
2886 GLenum format,
2887 GLenum type,
2888 GLsizei bufSize,
2889 const void *pixels)
2890 {
2891 if (context->getClientMajorVersion() < 3)
2892 {
2893 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2894 return false;
2895 }
2896
2897 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2898 {
2899 return false;
2900 }
2901
2902 return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
2903 xoffset, yoffset, zoffset, width, height, depth, 0,
2904 format, type, bufSize, pixels);
2905 }
2906
ValidateCompressedTexSubImage3D(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)2907 bool ValidateCompressedTexSubImage3D(const Context *context,
2908 angle::EntryPoint entryPoint,
2909 TextureTarget target,
2910 GLint level,
2911 GLint xoffset,
2912 GLint yoffset,
2913 GLint zoffset,
2914 GLsizei width,
2915 GLsizei height,
2916 GLsizei depth,
2917 GLenum format,
2918 GLsizei imageSize,
2919 const void *data)
2920 {
2921 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2922 {
2923 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
2924 return false;
2925 }
2926
2927 if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, true,
2928 xoffset, yoffset, zoffset, width, height, depth, 0, format,
2929 GL_NONE, -1, data))
2930 {
2931 return false;
2932 }
2933
2934 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2935
2936 if (!formatInfo.compressed)
2937 {
2938 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidCompressedFormat);
2939 return false;
2940 }
2941
2942 GLuint blockSize = 0;
2943 if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
2944 {
2945 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
2946 return false;
2947 }
2948
2949 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2950 {
2951 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2952 return false;
2953 }
2954
2955 if (data == nullptr)
2956 {
2957 if (context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
2958 {
2959 // If data is null, we need an unpack buffer to read from
2960 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
2961 return false;
2962 }
2963 }
2964
2965 return true;
2966 }
2967
ValidateCompressedTexSubImage3DRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2968 bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
2969 angle::EntryPoint entryPoint,
2970 TextureTarget target,
2971 GLint level,
2972 GLint xoffset,
2973 GLint yoffset,
2974 GLint zoffset,
2975 GLsizei width,
2976 GLsizei height,
2977 GLsizei depth,
2978 GLenum format,
2979 GLsizei imageSize,
2980 GLsizei dataSize,
2981 const void *data)
2982 {
2983 if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
2984 {
2985 return false;
2986 }
2987
2988 return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
2989 zoffset, width, height, depth, format, imageSize, data);
2990 }
2991
ValidateGenQueries(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * queries)2992 bool ValidateGenQueries(const Context *context,
2993 angle::EntryPoint entryPoint,
2994 GLsizei n,
2995 const QueryID *queries)
2996 {
2997 return ValidateGenOrDeleteES3(context, entryPoint, n);
2998 }
2999
ValidateDeleteQueries(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * queries)3000 bool ValidateDeleteQueries(const Context *context,
3001 angle::EntryPoint entryPoint,
3002 GLsizei n,
3003 const QueryID *queries)
3004 {
3005 return ValidateGenOrDeleteES3(context, entryPoint, n);
3006 }
3007
ValidateGenSamplers(const Context * context,angle::EntryPoint entryPoint,GLsizei count,const SamplerID * samplers)3008 bool ValidateGenSamplers(const Context *context,
3009 angle::EntryPoint entryPoint,
3010 GLsizei count,
3011 const SamplerID *samplers)
3012 {
3013 return ValidateGenOrDeleteCountES3(context, entryPoint, count);
3014 }
3015
ValidateDeleteSamplers(const Context * context,angle::EntryPoint entryPoint,GLsizei count,const SamplerID * samplers)3016 bool ValidateDeleteSamplers(const Context *context,
3017 angle::EntryPoint entryPoint,
3018 GLsizei count,
3019 const SamplerID *samplers)
3020 {
3021 return ValidateGenOrDeleteCountES3(context, entryPoint, count);
3022 }
3023
ValidateGenTransformFeedbacks(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const TransformFeedbackID * ids)3024 bool ValidateGenTransformFeedbacks(const Context *context,
3025 angle::EntryPoint entryPoint,
3026 GLsizei n,
3027 const TransformFeedbackID *ids)
3028 {
3029 return ValidateGenOrDeleteES3(context, entryPoint, n);
3030 }
3031
ValidateDeleteTransformFeedbacks(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const TransformFeedbackID * ids)3032 bool ValidateDeleteTransformFeedbacks(const Context *context,
3033 angle::EntryPoint entryPoint,
3034 GLsizei n,
3035 const TransformFeedbackID *ids)
3036 {
3037 if (!ValidateGenOrDeleteES3(context, entryPoint, n))
3038 {
3039 return false;
3040 }
3041 for (GLint i = 0; i < n; ++i)
3042 {
3043 auto *transformFeedback = context->getTransformFeedback(ids[i]);
3044 if (transformFeedback != nullptr && transformFeedback->isActive())
3045 {
3046 // ES 3.0.4 section 2.15.1 page 86
3047 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackActiveDelete);
3048 return false;
3049 }
3050 }
3051 return true;
3052 }
3053
ValidateGenVertexArrays(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const VertexArrayID * arrays)3054 bool ValidateGenVertexArrays(const Context *context,
3055 angle::EntryPoint entryPoint,
3056 GLsizei n,
3057 const VertexArrayID *arrays)
3058 {
3059 return ValidateGenOrDeleteES3(context, entryPoint, n);
3060 }
3061
ValidateDeleteVertexArrays(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const VertexArrayID * arrays)3062 bool ValidateDeleteVertexArrays(const Context *context,
3063 angle::EntryPoint entryPoint,
3064 GLsizei n,
3065 const VertexArrayID *arrays)
3066 {
3067 return ValidateGenOrDeleteES3(context, entryPoint, n);
3068 }
3069
ValidateBeginTransformFeedback(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode primitiveMode)3070 bool ValidateBeginTransformFeedback(const Context *context,
3071 angle::EntryPoint entryPoint,
3072 PrimitiveMode primitiveMode)
3073 {
3074 if (context->getClientMajorVersion() < 3)
3075 {
3076 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3077 return false;
3078 }
3079 switch (primitiveMode)
3080 {
3081 case PrimitiveMode::Triangles:
3082 case PrimitiveMode::Lines:
3083 case PrimitiveMode::Points:
3084 break;
3085
3086 default:
3087 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPrimitiveMode);
3088 return false;
3089 }
3090
3091 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3092 ASSERT(transformFeedback != nullptr);
3093
3094 if (transformFeedback->isActive())
3095 {
3096 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransfomFeedbackAlreadyActive);
3097 return false;
3098 }
3099
3100 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
3101 {
3102 const OffsetBindingPointer<Buffer> &buffer = transformFeedback->getIndexedBuffer(i);
3103 if (buffer.get())
3104 {
3105 if (buffer->isMapped())
3106 {
3107 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
3108 return false;
3109 }
3110 if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
3111 context->getExtensions().webglCompatibilityANGLE) &&
3112 buffer->isDoubleBoundForTransformFeedback())
3113 {
3114 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
3115 kTransformFeedbackBufferMultipleOutputs);
3116 return false;
3117 }
3118 }
3119 }
3120
3121 const ProgramExecutable *programExecutable =
3122 context->getState().getLinkedProgramExecutable(context);
3123 if (!programExecutable)
3124 {
3125 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotBound);
3126 return false;
3127 }
3128
3129 if (programExecutable->getLinkedTransformFeedbackVaryings().empty())
3130 {
3131 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoTransformFeedbackOutputVariables);
3132 return false;
3133 }
3134
3135 if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
3136 {
3137 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
3138 return false;
3139 }
3140
3141 return true;
3142 }
3143
ValidateGetBufferPointerv(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,void * const * params)3144 bool ValidateGetBufferPointerv(const Context *context,
3145 angle::EntryPoint entryPoint,
3146 BufferBinding target,
3147 GLenum pname,
3148 void *const *params)
3149 {
3150 if (context->getClientMajorVersion() < 3)
3151 {
3152 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3153 return false;
3154 }
3155
3156 return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
3157 }
3158
ValidateGetBufferPointervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)3159 bool ValidateGetBufferPointervRobustANGLE(const Context *context,
3160 angle::EntryPoint entryPoint,
3161 BufferBinding target,
3162 GLenum pname,
3163 GLsizei bufSize,
3164 const GLsizei *length,
3165 void *const *params)
3166 {
3167 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3168 {
3169 return false;
3170 }
3171
3172 GLsizei numParams = 0;
3173
3174 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES)
3175 {
3176 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3177 return false;
3178 }
3179
3180 if (!ValidateGetBufferPointervBase(context, entryPoint, target, pname, &numParams, params))
3181 {
3182 return false;
3183 }
3184
3185 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3186 {
3187 return false;
3188 }
3189
3190 SetRobustLengthParam(length, numParams);
3191
3192 return true;
3193 }
3194
ValidateUnmapBuffer(const Context * context,angle::EntryPoint entryPoint,BufferBinding target)3195 bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target)
3196 {
3197 if (context->getClientMajorVersion() < 3)
3198 {
3199 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3200 return false;
3201 }
3202
3203 return ValidateUnmapBufferBase(context, entryPoint, target);
3204 }
3205
ValidateMapBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3206 bool ValidateMapBufferRange(const Context *context,
3207 angle::EntryPoint entryPoint,
3208 BufferBinding target,
3209 GLintptr offset,
3210 GLsizeiptr length,
3211 GLbitfield access)
3212 {
3213 if (context->getClientMajorVersion() < 3)
3214 {
3215 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3216 return false;
3217 }
3218
3219 return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
3220 }
3221
ValidateFlushMappedBufferRange(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length)3222 bool ValidateFlushMappedBufferRange(const Context *context,
3223 angle::EntryPoint entryPoint,
3224 BufferBinding target,
3225 GLintptr offset,
3226 GLsizeiptr length)
3227 {
3228 if (context->getClientMajorVersion() < 3)
3229 {
3230 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3231 return false;
3232 }
3233
3234 return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
3235 }
3236
ValidateIndexedStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,GLsizei * length)3237 bool ValidateIndexedStateQuery(const Context *context,
3238 angle::EntryPoint entryPoint,
3239 GLenum pname,
3240 GLuint index,
3241 GLsizei *length)
3242 {
3243 if (length)
3244 {
3245 *length = 0;
3246 }
3247
3248 GLenum nativeType;
3249 unsigned int numParams;
3250 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
3251 {
3252 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
3253 return false;
3254 }
3255
3256 const Caps &caps = context->getCaps();
3257 switch (pname)
3258 {
3259 case GL_BLEND_SRC_RGB:
3260 case GL_BLEND_SRC_ALPHA:
3261 case GL_BLEND_DST_RGB:
3262 case GL_BLEND_DST_ALPHA:
3263 case GL_BLEND_EQUATION_RGB:
3264 case GL_BLEND_EQUATION_ALPHA:
3265 case GL_COLOR_WRITEMASK:
3266 if (!context->getExtensions().drawBuffersIndexedAny())
3267 {
3268 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kDrawBuffersIndexedExtensionNotAvailable);
3269 return false;
3270 }
3271 if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
3272 {
3273 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
3274 return false;
3275 }
3276 break;
3277 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
3278 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
3279 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
3280 if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
3281 {
3282 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxTransformFeedbackAttribs);
3283 return false;
3284 }
3285 break;
3286
3287 case GL_UNIFORM_BUFFER_START:
3288 case GL_UNIFORM_BUFFER_SIZE:
3289 case GL_UNIFORM_BUFFER_BINDING:
3290 if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
3291 {
3292 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
3293 return false;
3294 }
3295 break;
3296
3297 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
3298 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
3299 if (index >= 3u)
3300 {
3301 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxWorkgroupDimensions);
3302 return false;
3303 }
3304 break;
3305
3306 case GL_ATOMIC_COUNTER_BUFFER_START:
3307 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
3308 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
3309 if (context->getClientVersion() < ES_3_1)
3310 {
3311 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3312 return false;
3313 }
3314 if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
3315 {
3316 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
3317 kIndexExceedsMaxAtomicCounterBufferBindings);
3318 return false;
3319 }
3320 break;
3321
3322 case GL_SHADER_STORAGE_BUFFER_START:
3323 case GL_SHADER_STORAGE_BUFFER_SIZE:
3324 case GL_SHADER_STORAGE_BUFFER_BINDING:
3325 if (context->getClientVersion() < ES_3_1)
3326 {
3327 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3328 return false;
3329 }
3330 if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
3331 {
3332 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
3333 return false;
3334 }
3335 break;
3336
3337 case GL_VERTEX_BINDING_BUFFER:
3338 case GL_VERTEX_BINDING_DIVISOR:
3339 case GL_VERTEX_BINDING_OFFSET:
3340 case GL_VERTEX_BINDING_STRIDE:
3341 if (context->getClientVersion() < ES_3_1)
3342 {
3343 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3344 return false;
3345 }
3346 if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3347 {
3348 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3349 return false;
3350 }
3351 break;
3352 case GL_SAMPLE_MASK_VALUE:
3353 if (context->getClientVersion() < ES_3_1)
3354 {
3355 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3356 return false;
3357 }
3358 if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
3359 {
3360 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
3361 return false;
3362 }
3363 break;
3364 case GL_IMAGE_BINDING_NAME:
3365 case GL_IMAGE_BINDING_LEVEL:
3366 case GL_IMAGE_BINDING_LAYERED:
3367 case GL_IMAGE_BINDING_LAYER:
3368 case GL_IMAGE_BINDING_ACCESS:
3369 case GL_IMAGE_BINDING_FORMAT:
3370 if (context->getClientVersion() < ES_3_1)
3371 {
3372 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
3373 return false;
3374 }
3375 if (index >= static_cast<GLuint>(caps.maxImageUnits))
3376 {
3377 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxImageUnits);
3378 return false;
3379 }
3380 break;
3381 default:
3382 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3383 return false;
3384 }
3385
3386 if (length)
3387 {
3388 if (pname == GL_COLOR_WRITEMASK)
3389 {
3390 *length = 4;
3391 }
3392 else
3393 {
3394 *length = 1;
3395 }
3396 }
3397
3398 return true;
3399 }
3400
ValidateGetIntegeri_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint * data)3401 bool ValidateGetIntegeri_v(const Context *context,
3402 angle::EntryPoint entryPoint,
3403 GLenum target,
3404 GLuint index,
3405 const GLint *data)
3406 {
3407 if (context->getClientVersion() < ES_3_0)
3408 {
3409 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3410 return false;
3411 }
3412 return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3413 }
3414
ValidateGetIntegeri_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint * data)3415 bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
3416 angle::EntryPoint entryPoint,
3417 GLenum target,
3418 GLuint index,
3419 GLsizei bufSize,
3420 const GLsizei *length,
3421 const GLint *data)
3422 {
3423 if (context->getClientVersion() < ES_3_0)
3424 {
3425 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3426 return false;
3427 }
3428
3429 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3430 {
3431 return false;
3432 }
3433
3434 GLsizei numParams = 0;
3435
3436 if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3437 {
3438 return false;
3439 }
3440
3441 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3442 {
3443 return false;
3444 }
3445
3446 SetRobustLengthParam(length, numParams);
3447
3448 return true;
3449 }
3450
ValidateGetInteger64i_v(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,const GLint64 * data)3451 bool ValidateGetInteger64i_v(const Context *context,
3452 angle::EntryPoint entryPoint,
3453 GLenum target,
3454 GLuint index,
3455 const GLint64 *data)
3456 {
3457 if (context->getClientVersion() < ES_3_0)
3458 {
3459 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3460 return false;
3461 }
3462 return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
3463 }
3464
ValidateGetInteger64i_vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint64 * data)3465 bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
3466 angle::EntryPoint entryPoint,
3467 GLenum target,
3468 GLuint index,
3469 GLsizei bufSize,
3470 const GLsizei *length,
3471 const GLint64 *data)
3472 {
3473 if (context->getClientVersion() < ES_3_0)
3474 {
3475 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3476 return false;
3477 }
3478
3479 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3480 {
3481 return false;
3482 }
3483
3484 GLsizei numParams = 0;
3485
3486 if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
3487 {
3488 return false;
3489 }
3490
3491 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
3492 {
3493 return false;
3494 }
3495
3496 SetRobustLengthParam(length, numParams);
3497
3498 return true;
3499 }
3500
ValidateCopyBufferSubData(const Context * context,angle::EntryPoint entryPoint,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)3501 bool ValidateCopyBufferSubData(const Context *context,
3502 angle::EntryPoint entryPoint,
3503 BufferBinding readTarget,
3504 BufferBinding writeTarget,
3505 GLintptr readOffset,
3506 GLintptr writeOffset,
3507 GLsizeiptr size)
3508 {
3509 if (context->getClientMajorVersion() < 3)
3510 {
3511 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3512 return false;
3513 }
3514
3515 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
3516 {
3517 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
3518 return false;
3519 }
3520
3521 Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
3522 Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
3523
3524 if (!readBuffer || !writeBuffer)
3525 {
3526 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
3527 return false;
3528 }
3529
3530 // EXT_buffer_storage allows persistently mapped buffers to be updated via glCopyBufferSubData
3531 bool isReadPersistent = (readBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3532 bool isWritePersistent = (writeBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
3533
3534 // Verify that readBuffer and writeBuffer are not currently mapped unless persistent
3535 if ((readBuffer->isMapped() && !isReadPersistent) ||
3536 (writeBuffer->isMapped() && !isWritePersistent))
3537 {
3538 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
3539 return false;
3540 }
3541
3542 if (readBuffer->hasWebGLXFBBindingConflict(context->isWebGL()) ||
3543 writeBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
3544 {
3545 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
3546 return false;
3547 }
3548
3549 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
3550 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
3551 CheckedNumeric<GLintptr> checkedSize(size);
3552
3553 auto checkedReadSum = checkedReadOffset + checkedSize;
3554 auto checkedWriteSum = checkedWriteOffset + checkedSize;
3555
3556 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
3557 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
3558 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
3559 {
3560 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3561 return false;
3562 }
3563
3564 if (readOffset < 0 || writeOffset < 0)
3565 {
3566 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3567 return false;
3568 }
3569
3570 if (size < 0)
3571 {
3572 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3573 return false;
3574 }
3575
3576 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
3577 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
3578 {
3579 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBufferOffsetOverflow);
3580 return false;
3581 }
3582
3583 if (readBuffer == writeBuffer)
3584 {
3585 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
3586 if (!checkedOffsetDiff.IsValid())
3587 {
3588 // This shold not be possible.
3589 UNREACHABLE();
3590 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3591 return false;
3592 }
3593
3594 if (checkedOffsetDiff.ValueOrDie() < size)
3595 {
3596 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCopyAlias);
3597 return false;
3598 }
3599 }
3600
3601 return true;
3602 }
3603
ValidateGetStringi(const Context * context,angle::EntryPoint entryPoint,GLenum name,GLuint index)3604 bool ValidateGetStringi(const Context *context,
3605 angle::EntryPoint entryPoint,
3606 GLenum name,
3607 GLuint index)
3608 {
3609 if (context->getClientMajorVersion() < 3)
3610 {
3611 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3612 return false;
3613 }
3614
3615 switch (name)
3616 {
3617 case GL_EXTENSIONS:
3618 if (index >= context->getExtensionStringCount())
3619 {
3620 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsNumExtensions);
3621 return false;
3622 }
3623 break;
3624
3625 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3626 if (!context->getExtensions().requestExtensionANGLE)
3627 {
3628 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
3629 return false;
3630 }
3631 if (index >= context->getRequestableExtensionStringCount())
3632 {
3633 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsNumRequestableExtensions);
3634 return false;
3635 }
3636 break;
3637
3638 default:
3639 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
3640 return false;
3641 }
3642
3643 return true;
3644 }
3645
ValidateRenderbufferStorageMultisample(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3646 bool ValidateRenderbufferStorageMultisample(const Context *context,
3647 angle::EntryPoint entryPoint,
3648 GLenum target,
3649 GLsizei samples,
3650 GLenum internalformat,
3651 GLsizei width,
3652 GLsizei height)
3653 {
3654 if (context->getClientMajorVersion() < 3)
3655 {
3656 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3657 return false;
3658 }
3659
3660 if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
3661 internalformat, width, height))
3662 {
3663 return false;
3664 }
3665
3666 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
3667 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
3668 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
3669 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
3670 if (formatInfo.isInt())
3671 {
3672 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
3673 samples > context->getCaps().maxIntegerSamples)
3674 {
3675 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3676 return false;
3677 }
3678 }
3679
3680 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
3681 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3682 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3683 {
3684 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3685 return false;
3686 }
3687
3688 return true;
3689 }
3690
ValidateVertexAttribIPointer(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)3691 bool ValidateVertexAttribIPointer(const Context *context,
3692 angle::EntryPoint entryPoint,
3693 GLuint index,
3694 GLint size,
3695 VertexAttribType type,
3696 GLsizei stride,
3697 const void *pointer)
3698 {
3699 if (context->getClientMajorVersion() < 3)
3700 {
3701 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3702 return false;
3703 }
3704
3705 if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type))
3706 {
3707 return false;
3708 }
3709
3710 if (stride < 0)
3711 {
3712 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeStride);
3713 return false;
3714 }
3715
3716 const Caps &caps = context->getCaps();
3717 if (context->getClientVersion() >= ES_3_1)
3718 {
3719 if (stride > caps.maxVertexAttribStride)
3720 {
3721 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
3722 return false;
3723 }
3724
3725 // [OpenGL ES 3.1] Section 10.3.1 page 245:
3726 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3727 // validation should be inherited.
3728 if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3729 {
3730 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3731 return false;
3732 }
3733 }
3734
3735 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3736 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3737 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3738 // and the pointer argument is not NULL.
3739 if (context->getState().getVertexArrayId().value != 0 &&
3740 context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
3741 {
3742 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kClientDataInVertexArray);
3743 return false;
3744 }
3745
3746 if (context->getExtensions().webglCompatibilityANGLE)
3747 {
3748 if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, false, stride, pointer,
3749 true))
3750 {
3751 return false;
3752 }
3753 }
3754
3755 return true;
3756 }
3757
ValidateGetSynciv(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * values)3758 bool ValidateGetSynciv(const Context *context,
3759 angle::EntryPoint entryPoint,
3760 SyncID syncPacked,
3761 GLenum pname,
3762 GLsizei bufSize,
3763 const GLsizei *length,
3764 const GLint *values)
3765 {
3766 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
3767 {
3768 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3769 return false;
3770 }
3771
3772 if (bufSize < 0)
3773 {
3774 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
3775 return false;
3776 }
3777
3778 if (context->isContextLost())
3779 {
3780 ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
3781
3782 if (pname == GL_SYNC_STATUS)
3783 {
3784 // Generate an error but still return true, the context still needs to return a
3785 // value in this case.
3786 return true;
3787 }
3788 else
3789 {
3790 return false;
3791 }
3792 }
3793
3794 Sync *syncObject = context->getSync(syncPacked);
3795 if (!syncObject)
3796 {
3797 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
3798 return false;
3799 }
3800
3801 switch (pname)
3802 {
3803 case GL_OBJECT_TYPE:
3804 case GL_SYNC_CONDITION:
3805 case GL_SYNC_FLAGS:
3806 case GL_SYNC_STATUS:
3807 break;
3808
3809 default:
3810 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
3811 return false;
3812 }
3813
3814 return true;
3815 }
3816
ValidateDrawElementsInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei instanceCount)3817 bool ValidateDrawElementsInstanced(const Context *context,
3818 angle::EntryPoint entryPoint,
3819 PrimitiveMode mode,
3820 GLsizei count,
3821 DrawElementsType type,
3822 const void *indices,
3823 GLsizei instanceCount)
3824 {
3825 if (context->getClientMajorVersion() < 3)
3826 {
3827 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
3828 return false;
3829 }
3830
3831 return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3832 instanceCount, 0);
3833 }
3834
ValidateMultiDrawArraysInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)3835 bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
3836 angle::EntryPoint entryPoint,
3837 PrimitiveMode mode,
3838 const GLint *firsts,
3839 const GLsizei *counts,
3840 const GLsizei *instanceCounts,
3841 GLsizei drawcount)
3842 {
3843 if (!context->getExtensions().multiDrawANGLE)
3844 {
3845 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3846 return false;
3847 }
3848 if (context->getClientMajorVersion() < 3)
3849 {
3850 if (!context->getExtensions().instancedArraysAny())
3851 {
3852 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3853 return false;
3854 }
3855 if (!ValidateDrawInstancedANGLE(context, entryPoint))
3856 {
3857 return false;
3858 }
3859 }
3860 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3861 {
3862 if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID],
3863 counts[drawID], instanceCounts[drawID], 0))
3864 {
3865 return false;
3866 }
3867 }
3868 return true;
3869 }
3870
ValidateMultiDrawElementsInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)3871 bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
3872 angle::EntryPoint entryPoint,
3873 PrimitiveMode mode,
3874 const GLsizei *counts,
3875 DrawElementsType type,
3876 const GLvoid *const *indices,
3877 const GLsizei *instanceCounts,
3878 GLsizei drawcount)
3879 {
3880 if (!context->getExtensions().multiDrawANGLE)
3881 {
3882 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3883 return false;
3884 }
3885 if (context->getClientMajorVersion() < 3)
3886 {
3887 if (!context->getExtensions().instancedArraysAny())
3888 {
3889 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3890 return false;
3891 }
3892 if (!ValidateDrawInstancedANGLE(context, entryPoint))
3893 {
3894 return false;
3895 }
3896 }
3897 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3898 {
3899 if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type,
3900 indices[drawID], instanceCounts[drawID], 0))
3901 {
3902 return false;
3903 }
3904 }
3905 return true;
3906 }
3907
ValidateDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)3908 bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3909 angle::EntryPoint entryPoint,
3910 PrimitiveMode mode,
3911 GLint first,
3912 GLsizei count,
3913 GLsizei instanceCount,
3914 GLuint baseInstance)
3915 {
3916 if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3917 {
3918 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3919 return false;
3920 }
3921
3922 return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount,
3923 baseInstance);
3924 }
3925
ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const GLvoid * indices,GLsizei instanceCount,GLint baseVertex,GLuint baseInstance)3926 bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3927 angle::EntryPoint entryPoint,
3928 PrimitiveMode mode,
3929 GLsizei count,
3930 DrawElementsType type,
3931 const GLvoid *indices,
3932 GLsizei instanceCount,
3933 GLint baseVertex,
3934 GLuint baseInstance)
3935 {
3936 if (!context->getExtensions().baseVertexBaseInstanceANGLE)
3937 {
3938 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3939 return false;
3940 }
3941
3942 return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
3943 instanceCount, baseInstance);
3944 }
3945
ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode modePacked,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)3946 bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3947 angle::EntryPoint entryPoint,
3948 PrimitiveMode modePacked,
3949 const GLint *firsts,
3950 const GLsizei *counts,
3951 const GLsizei *instanceCounts,
3952 const GLuint *baseInstances,
3953 GLsizei drawcount)
3954 {
3955 if (!context->getExtensions().multiDrawANGLE)
3956 {
3957 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3958 return false;
3959 }
3960 if (drawcount < 0)
3961 {
3962 return false;
3963 }
3964 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3965 {
3966 if (!ValidateDrawArraysInstancedBase(context, entryPoint, modePacked, firsts[drawID],
3967 counts[drawID], instanceCounts[drawID],
3968 baseInstances[drawID]))
3969 {
3970 return false;
3971 }
3972 }
3973 return true;
3974 }
3975
ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode modePacked,const GLsizei * counts,DrawElementsType typePacked,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)3976 bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3977 angle::EntryPoint entryPoint,
3978 PrimitiveMode modePacked,
3979 const GLsizei *counts,
3980 DrawElementsType typePacked,
3981 const GLvoid *const *indices,
3982 const GLsizei *instanceCounts,
3983 const GLint *baseVertices,
3984 const GLuint *baseInstances,
3985 GLsizei drawcount)
3986 {
3987 if (!context->getExtensions().multiDrawANGLE)
3988 {
3989 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
3990 return false;
3991 }
3992 if (drawcount < 0)
3993 {
3994 return false;
3995 }
3996 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3997 {
3998 if (!ValidateDrawElementsInstancedBase(context, entryPoint, modePacked, counts[drawID],
3999 typePacked, indices[drawID], instanceCounts[drawID],
4000 baseInstances[drawID]))
4001 {
4002 return false;
4003 }
4004 }
4005 return true;
4006 }
4007
ValidateFramebufferTextureMultiviewOVR(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint baseViewIndex,GLsizei numViews)4008 bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
4009 angle::EntryPoint entryPoint,
4010 GLenum target,
4011 GLenum attachment,
4012 TextureID texture,
4013 GLint level,
4014 GLint baseViewIndex,
4015 GLsizei numViews)
4016 {
4017 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment,
4018 texture, level, numViews))
4019 {
4020 return false;
4021 }
4022
4023 if (texture.value != 0)
4024 {
4025 if (baseViewIndex < 0)
4026 {
4027 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBaseViewIndex);
4028 return false;
4029 }
4030
4031 Texture *tex = context->getTexture(texture);
4032 ASSERT(tex);
4033
4034 switch (tex->getType())
4035 {
4036 case TextureType::_2DArray:
4037 case TextureType::_2DMultisampleArray:
4038 {
4039 if (tex->getType() == TextureType::_2DMultisampleArray)
4040 {
4041 if (!context->getExtensions().multiviewMultisampleANGLE)
4042 {
4043 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureType);
4044 return false;
4045 }
4046 }
4047
4048 const Caps &caps = context->getCaps();
4049 if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
4050 {
4051 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kViewsExceedMaxArrayLayers);
4052 return false;
4053 }
4054
4055 break;
4056 }
4057 default:
4058 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureType);
4059 return false;
4060 }
4061
4062 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, entryPoint, tex, level))
4063 {
4064 return false;
4065 }
4066 }
4067
4068 return true;
4069 }
4070
ValidateUniform1ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0)4071 bool ValidateUniform1ui(const Context *context,
4072 angle::EntryPoint entryPoint,
4073 UniformLocation location,
4074 GLuint v0)
4075 {
4076 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1);
4077 }
4078
ValidateUniform2ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1)4079 bool ValidateUniform2ui(const Context *context,
4080 angle::EntryPoint entryPoint,
4081 UniformLocation location,
4082 GLuint v0,
4083 GLuint v1)
4084 {
4085 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1);
4086 }
4087
ValidateUniform3ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2)4088 bool ValidateUniform3ui(const Context *context,
4089 angle::EntryPoint entryPoint,
4090 UniformLocation location,
4091 GLuint v0,
4092 GLuint v1,
4093 GLuint v2)
4094 {
4095 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1);
4096 }
4097
ValidateUniform4ui(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)4098 bool ValidateUniform4ui(const Context *context,
4099 angle::EntryPoint entryPoint,
4100 UniformLocation location,
4101 GLuint v0,
4102 GLuint v1,
4103 GLuint v2,
4104 GLuint v3)
4105 {
4106 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1);
4107 }
4108
ValidateUniform1uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4109 bool ValidateUniform1uiv(const Context *context,
4110 angle::EntryPoint entryPoint,
4111 UniformLocation location,
4112 GLsizei count,
4113 const GLuint *value)
4114 {
4115 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count);
4116 }
4117
ValidateUniform2uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4118 bool ValidateUniform2uiv(const Context *context,
4119 angle::EntryPoint entryPoint,
4120 UniformLocation location,
4121 GLsizei count,
4122 const GLuint *value)
4123 {
4124 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count);
4125 }
4126
ValidateUniform3uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4127 bool ValidateUniform3uiv(const Context *context,
4128 angle::EntryPoint entryPoint,
4129 UniformLocation location,
4130 GLsizei count,
4131 const GLuint *value)
4132 {
4133 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count);
4134 }
4135
ValidateUniform4uiv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLuint * value)4136 bool ValidateUniform4uiv(const Context *context,
4137 angle::EntryPoint entryPoint,
4138 UniformLocation location,
4139 GLsizei count,
4140 const GLuint *value)
4141 {
4142 return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count);
4143 }
4144
ValidateIsQuery(const Context * context,angle::EntryPoint entryPoint,QueryID id)4145 bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id)
4146 {
4147 if (context->getClientMajorVersion() < 3)
4148 {
4149 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4150 return false;
4151 }
4152
4153 return true;
4154 }
4155
ValidateUniformMatrix2x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4156 bool ValidateUniformMatrix2x3fv(const Context *context,
4157 angle::EntryPoint entryPoint,
4158 UniformLocation location,
4159 GLsizei count,
4160 GLboolean transpose,
4161 const GLfloat *value)
4162 {
4163 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count,
4164 transpose);
4165 }
4166
ValidateUniformMatrix3x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4167 bool ValidateUniformMatrix3x2fv(const Context *context,
4168 angle::EntryPoint entryPoint,
4169 UniformLocation location,
4170 GLsizei count,
4171 GLboolean transpose,
4172 const GLfloat *value)
4173 {
4174 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count,
4175 transpose);
4176 }
4177
ValidateUniformMatrix2x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4178 bool ValidateUniformMatrix2x4fv(const Context *context,
4179 angle::EntryPoint entryPoint,
4180 UniformLocation location,
4181 GLsizei count,
4182 GLboolean transpose,
4183 const GLfloat *value)
4184 {
4185 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count,
4186 transpose);
4187 }
4188
ValidateUniformMatrix4x2fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4189 bool ValidateUniformMatrix4x2fv(const Context *context,
4190 angle::EntryPoint entryPoint,
4191 UniformLocation location,
4192 GLsizei count,
4193 GLboolean transpose,
4194 const GLfloat *value)
4195 {
4196 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count,
4197 transpose);
4198 }
4199
ValidateUniformMatrix3x4fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4200 bool ValidateUniformMatrix3x4fv(const Context *context,
4201 angle::EntryPoint entryPoint,
4202 UniformLocation location,
4203 GLsizei count,
4204 GLboolean transpose,
4205 const GLfloat *value)
4206 {
4207 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count,
4208 transpose);
4209 }
4210
ValidateUniformMatrix4x3fv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)4211 bool ValidateUniformMatrix4x3fv(const Context *context,
4212 angle::EntryPoint entryPoint,
4213 UniformLocation location,
4214 GLsizei count,
4215 GLboolean transpose,
4216 const GLfloat *value)
4217 {
4218 return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count,
4219 transpose);
4220 }
4221
ValidateEndTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4222 bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4223 {
4224 if (context->getClientMajorVersion() < 3)
4225 {
4226 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4227 return false;
4228 }
4229
4230 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4231 ASSERT(transformFeedback != nullptr);
4232
4233 if (!transformFeedback->isActive())
4234 {
4235 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4236 return false;
4237 }
4238
4239 return true;
4240 }
4241
ValidateTransformFeedbackVaryings(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)4242 bool ValidateTransformFeedbackVaryings(const Context *context,
4243 angle::EntryPoint entryPoint,
4244 ShaderProgramID program,
4245 GLsizei count,
4246 const GLchar *const *varyings,
4247 GLenum bufferMode)
4248 {
4249 if (context->getClientMajorVersion() < 3)
4250 {
4251 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4252 return false;
4253 }
4254
4255 if (count < 0)
4256 {
4257 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4258 return false;
4259 }
4260
4261 switch (bufferMode)
4262 {
4263 case GL_INTERLEAVED_ATTRIBS:
4264 break;
4265 case GL_SEPARATE_ATTRIBS:
4266 {
4267 const Caps &caps = context->getCaps();
4268 if (count > caps.maxTransformFeedbackSeparateAttributes)
4269 {
4270 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTransformFeedbackAttribsCount);
4271 return false;
4272 }
4273 break;
4274 }
4275 default:
4276 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, bufferMode);
4277 return false;
4278 }
4279
4280 Program *programObject = GetValidProgram(context, entryPoint, program);
4281 if (!programObject)
4282 {
4283 return false;
4284 }
4285
4286 return true;
4287 }
4288
ValidateGetTransformFeedbackVarying(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint index,GLsizei bufSize,const GLsizei * length,const GLsizei * size,const GLenum * type,const GLchar * name)4289 bool ValidateGetTransformFeedbackVarying(const Context *context,
4290 angle::EntryPoint entryPoint,
4291 ShaderProgramID program,
4292 GLuint index,
4293 GLsizei bufSize,
4294 const GLsizei *length,
4295 const GLsizei *size,
4296 const GLenum *type,
4297 const GLchar *name)
4298 {
4299 if (context->getClientMajorVersion() < 3)
4300 {
4301 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4302 return false;
4303 }
4304
4305 if (bufSize < 0)
4306 {
4307 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
4308 return false;
4309 }
4310
4311 Program *programObject = GetValidProgram(context, entryPoint, program);
4312 if (!programObject)
4313 {
4314 return false;
4315 }
4316
4317 if (index >= static_cast<GLuint>(
4318 programObject->getExecutable().getLinkedTransformFeedbackVaryings().size()))
4319 {
4320 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTransformFeedbackVaryingIndexOutOfRange);
4321 return false;
4322 }
4323
4324 return true;
4325 }
4326
ValidateBindTransformFeedback(const Context * context,angle::EntryPoint entryPoint,GLenum target,TransformFeedbackID id)4327 bool ValidateBindTransformFeedback(const Context *context,
4328 angle::EntryPoint entryPoint,
4329 GLenum target,
4330 TransformFeedbackID id)
4331 {
4332 if (context->getClientMajorVersion() < 3)
4333 {
4334 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4335 return false;
4336 }
4337
4338 switch (target)
4339 {
4340 case GL_TRANSFORM_FEEDBACK:
4341 {
4342 // Cannot bind a transform feedback object if the current one is started and not
4343 // paused (3.0.2 pg 85 section 2.14.1)
4344 if (context->getState().isTransformFeedbackActiveUnpaused())
4345 {
4346 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
4347 return false;
4348 }
4349
4350 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
4351 // 2.14.1)
4352 if (!context->isTransformFeedbackGenerated(id))
4353 {
4354 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackDoesNotExist);
4355 return false;
4356 }
4357 }
4358 break;
4359
4360 default:
4361 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, target);
4362 return false;
4363 }
4364
4365 return true;
4366 }
4367
ValidateIsTransformFeedback(const Context * context,angle::EntryPoint entryPoint,TransformFeedbackID id)4368 bool ValidateIsTransformFeedback(const Context *context,
4369 angle::EntryPoint entryPoint,
4370 TransformFeedbackID id)
4371 {
4372 if (context->getClientMajorVersion() < 3)
4373 {
4374 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4375 return false;
4376 }
4377
4378 return true;
4379 }
4380
ValidatePauseTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4381 bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4382 {
4383 if (context->getClientMajorVersion() < 3)
4384 {
4385 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4386 return false;
4387 }
4388
4389 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4390 ASSERT(transformFeedback != nullptr);
4391
4392 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
4393 if (!transformFeedback->isActive())
4394 {
4395 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4396 return false;
4397 }
4398
4399 if (transformFeedback->isPaused())
4400 {
4401 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackPaused);
4402 return false;
4403 }
4404
4405 return true;
4406 }
4407
ValidateResumeTransformFeedback(const Context * context,angle::EntryPoint entryPoint)4408 bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
4409 {
4410 if (context->getClientMajorVersion() < 3)
4411 {
4412 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4413 return false;
4414 }
4415
4416 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
4417 ASSERT(transformFeedback != nullptr);
4418
4419 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
4420 if (!transformFeedback->isActive())
4421 {
4422 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
4423 return false;
4424 }
4425
4426 if (!transformFeedback->isPaused())
4427 {
4428 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
4429 return false;
4430 }
4431
4432 if (!ValidateProgramExecutableXFBBuffersPresent(
4433 context, context->getState().getLinkedProgramExecutable(context)))
4434 {
4435 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
4436 return false;
4437 }
4438
4439 return true;
4440 }
4441
ValidateVertexAttribI4i(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,GLint x,GLint y,GLint z,GLint w)4442 bool ValidateVertexAttribI4i(const PrivateState &state,
4443 ErrorSet *errors,
4444 angle::EntryPoint entryPoint,
4445 GLuint index,
4446 GLint x,
4447 GLint y,
4448 GLint z,
4449 GLint w)
4450 {
4451 if (state.getClientMajorVersion() < 3)
4452 {
4453 errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4454 return false;
4455 }
4456
4457 return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4458 }
4459
ValidateVertexAttribI4ui(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)4460 bool ValidateVertexAttribI4ui(const PrivateState &state,
4461 ErrorSet *errors,
4462 angle::EntryPoint entryPoint,
4463 GLuint index,
4464 GLuint x,
4465 GLuint y,
4466 GLuint z,
4467 GLuint w)
4468 {
4469 if (state.getClientMajorVersion() < 3)
4470 {
4471 errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4472 return false;
4473 }
4474
4475 return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4476 }
4477
ValidateVertexAttribI4iv(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,const GLint * v)4478 bool ValidateVertexAttribI4iv(const PrivateState &state,
4479 ErrorSet *errors,
4480 angle::EntryPoint entryPoint,
4481 GLuint index,
4482 const GLint *v)
4483 {
4484 if (state.getClientMajorVersion() < 3)
4485 {
4486 errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4487 return false;
4488 }
4489
4490 return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4491 }
4492
ValidateVertexAttribI4uiv(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint index,const GLuint * v)4493 bool ValidateVertexAttribI4uiv(const PrivateState &state,
4494 ErrorSet *errors,
4495 angle::EntryPoint entryPoint,
4496 GLuint index,
4497 const GLuint *v)
4498 {
4499 if (state.getClientMajorVersion() < 3)
4500 {
4501 errors->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
4502 return false;
4503 }
4504
4505 return ValidateVertexAttribIndex(state, errors, entryPoint, index);
4506 }
4507
ValidateGetFragDataLocation(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * name)4508 bool ValidateGetFragDataLocation(const Context *context,
4509 angle::EntryPoint entryPoint,
4510 ShaderProgramID program,
4511 const GLchar *name)
4512 {
4513 if (context->getClientMajorVersion() < 3)
4514 {
4515 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4516 return false;
4517 }
4518
4519 Program *programObject = GetValidProgram(context, entryPoint, program);
4520 if (!programObject)
4521 {
4522 return false;
4523 }
4524
4525 if (!programObject->isLinked())
4526 {
4527 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
4528 return false;
4529 }
4530
4531 return true;
4532 }
4533
ValidateGetUniformIndices(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLchar * const * uniformNames,const GLuint * uniformIndices)4534 bool ValidateGetUniformIndices(const Context *context,
4535 angle::EntryPoint entryPoint,
4536 ShaderProgramID program,
4537 GLsizei uniformCount,
4538 const GLchar *const *uniformNames,
4539 const GLuint *uniformIndices)
4540 {
4541 if (context->getClientMajorVersion() < 3)
4542 {
4543 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4544 return false;
4545 }
4546
4547 if (uniformCount < 0)
4548 {
4549 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4550 return false;
4551 }
4552
4553 Program *programObject = GetValidProgram(context, entryPoint, program);
4554 if (!programObject)
4555 {
4556 return false;
4557 }
4558
4559 return true;
4560 }
4561
ValidateGetActiveUniformsiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,const GLint * params)4562 bool ValidateGetActiveUniformsiv(const Context *context,
4563 angle::EntryPoint entryPoint,
4564 ShaderProgramID program,
4565 GLsizei uniformCount,
4566 const GLuint *uniformIndices,
4567 GLenum pname,
4568 const GLint *params)
4569 {
4570 if (context->getClientMajorVersion() < 3)
4571 {
4572 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4573 return false;
4574 }
4575
4576 if (uniformCount < 0)
4577 {
4578 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
4579 return false;
4580 }
4581
4582 Program *programObject = GetValidProgram(context, entryPoint, program);
4583 if (!programObject)
4584 {
4585 return false;
4586 }
4587
4588 switch (pname)
4589 {
4590 case GL_UNIFORM_TYPE:
4591 case GL_UNIFORM_SIZE:
4592 break;
4593 case GL_UNIFORM_NAME_LENGTH:
4594 if (context->getExtensions().webglCompatibilityANGLE)
4595 {
4596 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
4597 return false;
4598 }
4599 break;
4600 case GL_UNIFORM_BLOCK_INDEX:
4601 case GL_UNIFORM_OFFSET:
4602 case GL_UNIFORM_ARRAY_STRIDE:
4603 case GL_UNIFORM_MATRIX_STRIDE:
4604 case GL_UNIFORM_IS_ROW_MAJOR:
4605 break;
4606
4607 default:
4608 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
4609 return false;
4610 }
4611
4612 const size_t programUniformCount = programObject->getExecutable().getUniforms().size();
4613 if (uniformCount > static_cast<GLsizei>(programUniformCount))
4614 {
4615 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4616 return false;
4617 }
4618
4619 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
4620 {
4621 const GLuint index = uniformIndices[uniformId];
4622
4623 if (index >= programUniformCount)
4624 {
4625 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
4626 return false;
4627 }
4628 }
4629
4630 return true;
4631 }
4632
ValidateGetUniformBlockIndex(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const GLchar * uniformBlockName)4633 bool ValidateGetUniformBlockIndex(const Context *context,
4634 angle::EntryPoint entryPoint,
4635 ShaderProgramID program,
4636 const GLchar *uniformBlockName)
4637 {
4638 if (context->getClientMajorVersion() < 3)
4639 {
4640 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4641 return false;
4642 }
4643
4644 Program *programObject = GetValidProgram(context, entryPoint, program);
4645 if (!programObject)
4646 {
4647 return false;
4648 }
4649
4650 return true;
4651 }
4652
ValidateGetActiveUniformBlockiv(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,const GLint * params)4653 bool ValidateGetActiveUniformBlockiv(const Context *context,
4654 angle::EntryPoint entryPoint,
4655 ShaderProgramID program,
4656 UniformBlockIndex uniformBlockIndex,
4657 GLenum pname,
4658 const GLint *params)
4659 {
4660 return ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex,
4661 pname, nullptr);
4662 }
4663
ValidateGetActiveUniformBlockName(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLsizei bufSize,const GLsizei * length,const GLchar * uniformBlockName)4664 bool ValidateGetActiveUniformBlockName(const Context *context,
4665 angle::EntryPoint entryPoint,
4666 ShaderProgramID program,
4667 UniformBlockIndex uniformBlockIndex,
4668 GLsizei bufSize,
4669 const GLsizei *length,
4670 const GLchar *uniformBlockName)
4671 {
4672 if (context->getClientMajorVersion() < 3)
4673 {
4674 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4675 return false;
4676 }
4677
4678 Program *programObject = GetValidProgram(context, entryPoint, program);
4679 if (!programObject)
4680 {
4681 return false;
4682 }
4683
4684 if (uniformBlockIndex.value >= programObject->getExecutable().getUniformBlocks().size())
4685 {
4686 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
4687 return false;
4688 }
4689
4690 return true;
4691 }
4692
ValidateUniformBlockBinding(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)4693 bool ValidateUniformBlockBinding(const Context *context,
4694 angle::EntryPoint entryPoint,
4695 ShaderProgramID program,
4696 UniformBlockIndex uniformBlockIndex,
4697 GLuint uniformBlockBinding)
4698 {
4699 if (context->getClientMajorVersion() < 3)
4700 {
4701 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4702 return false;
4703 }
4704
4705 if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
4706 {
4707 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4708 return false;
4709 }
4710
4711 Program *programObject = GetValidProgram(context, entryPoint, program);
4712 if (!programObject)
4713 {
4714 return false;
4715 }
4716
4717 // if never linked, there won't be any uniform blocks
4718 if (uniformBlockIndex.value >= programObject->getExecutable().getUniformBlocks().size())
4719 {
4720 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4721 return false;
4722 }
4723
4724 return true;
4725 }
4726
ValidateDrawArraysInstanced(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4727 bool ValidateDrawArraysInstanced(const Context *context,
4728 angle::EntryPoint entryPoint,
4729 PrimitiveMode mode,
4730 GLint first,
4731 GLsizei count,
4732 GLsizei primcount)
4733 {
4734 if (context->getClientMajorVersion() < 3)
4735 {
4736 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4737 return false;
4738 }
4739
4740 return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0);
4741 }
4742
ValidateFenceSync(const Context * context,angle::EntryPoint entryPoint,GLenum condition,GLbitfield flags)4743 bool ValidateFenceSync(const Context *context,
4744 angle::EntryPoint entryPoint,
4745 GLenum condition,
4746 GLbitfield flags)
4747 {
4748 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4749 {
4750 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4751 return false;
4752 }
4753
4754 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
4755 {
4756 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFenceCondition);
4757 return false;
4758 }
4759
4760 if (flags != 0)
4761 {
4762 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4763 return false;
4764 }
4765
4766 return true;
4767 }
4768
ValidateIsSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked)4769 bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked)
4770 {
4771 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4772 {
4773 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4774 return false;
4775 }
4776
4777 return true;
4778 }
4779
ValidateDeleteSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked)4780 bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, SyncID syncPacked)
4781 {
4782 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4783 {
4784 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4785 return false;
4786 }
4787
4788 if (syncPacked.value != 0 && !context->getSync(syncPacked))
4789 {
4790 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4791 return false;
4792 }
4793
4794 return true;
4795 }
4796
ValidateClientWaitSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLbitfield flags,GLuint64 timeout)4797 bool ValidateClientWaitSync(const Context *context,
4798 angle::EntryPoint entryPoint,
4799 SyncID syncPacked,
4800 GLbitfield flags,
4801 GLuint64 timeout)
4802 {
4803 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4804 {
4805 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4806 return false;
4807 }
4808
4809 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
4810 {
4811 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4812 return false;
4813 }
4814
4815 Sync *clientWaitSync = context->getSync(syncPacked);
4816 if (!clientWaitSync)
4817 {
4818 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4819 return false;
4820 }
4821
4822 return true;
4823 }
4824
ValidateWaitSync(const Context * context,angle::EntryPoint entryPoint,SyncID syncPacked,GLbitfield flags,GLuint64 timeout)4825 bool ValidateWaitSync(const Context *context,
4826 angle::EntryPoint entryPoint,
4827 SyncID syncPacked,
4828 GLbitfield flags,
4829 GLuint64 timeout)
4830 {
4831 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4832 {
4833 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4834 return false;
4835 }
4836
4837 if (flags != 0)
4838 {
4839 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlags);
4840 return false;
4841 }
4842
4843 if (timeout != GL_TIMEOUT_IGNORED)
4844 {
4845 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTimeout);
4846 return false;
4847 }
4848
4849 Sync *waitSync = context->getSync(syncPacked);
4850 if (!waitSync)
4851 {
4852 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSyncMissing);
4853 return false;
4854 }
4855
4856 return true;
4857 }
4858
ValidateGetInteger64v(const Context * context,angle::EntryPoint entryPoint,GLenum pname,const GLint64 * params)4859 bool ValidateGetInteger64v(const Context *context,
4860 angle::EntryPoint entryPoint,
4861 GLenum pname,
4862 const GLint64 *params)
4863 {
4864 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
4865 {
4866 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4867 return false;
4868 }
4869
4870 GLenum nativeType = GL_NONE;
4871 unsigned int numParams = 0;
4872 if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
4873 {
4874 return false;
4875 }
4876
4877 return true;
4878 }
4879
ValidateIsSampler(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler)4880 bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler)
4881 {
4882 if (context->getClientMajorVersion() < 3)
4883 {
4884 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4885 return false;
4886 }
4887
4888 return true;
4889 }
4890
ValidateBindSampler(const Context * context,angle::EntryPoint entryPoint,GLuint unit,SamplerID sampler)4891 bool ValidateBindSampler(const Context *context,
4892 angle::EntryPoint entryPoint,
4893 GLuint unit,
4894 SamplerID sampler)
4895 {
4896 if (context->getClientMajorVersion() < 3)
4897 {
4898 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4899 return false;
4900 }
4901
4902 if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
4903 {
4904 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
4905 return false;
4906 }
4907
4908 if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
4909 {
4910 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCombinedImageUnit);
4911 return false;
4912 }
4913
4914 return true;
4915 }
4916
ValidateVertexAttribDivisor(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLuint divisor)4917 bool ValidateVertexAttribDivisor(const Context *context,
4918 angle::EntryPoint entryPoint,
4919 GLuint index,
4920 GLuint divisor)
4921 {
4922 if (context->getClientMajorVersion() < 3)
4923 {
4924 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4925 return false;
4926 }
4927
4928 return ValidateVertexAttribIndex(context->getPrivateState(),
4929 context->getMutableErrorSetForValidation(), entryPoint, index);
4930 }
4931
ValidateTexStorage2D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)4932 bool ValidateTexStorage2D(const Context *context,
4933 angle::EntryPoint entryPoint,
4934 TextureType target,
4935 GLsizei levels,
4936 GLenum internalformat,
4937 GLsizei width,
4938 GLsizei height)
4939 {
4940 if (context->getClientMajorVersion() < 3)
4941 {
4942 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4943 return false;
4944 }
4945
4946 if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat,
4947 width, height, 1))
4948 {
4949 return false;
4950 }
4951
4952 return true;
4953 }
4954
ValidateTexStorage3D(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)4955 bool ValidateTexStorage3D(const Context *context,
4956 angle::EntryPoint entryPoint,
4957 TextureType target,
4958 GLsizei levels,
4959 GLenum internalformat,
4960 GLsizei width,
4961 GLsizei height,
4962 GLsizei depth)
4963 {
4964 if (context->getClientMajorVersion() < 3)
4965 {
4966 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4967 return false;
4968 }
4969
4970 if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
4971 width, height, depth))
4972 {
4973 return false;
4974 }
4975
4976 return true;
4977 }
4978
ValidateGetBufferParameteri64v(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,const GLint64 * params)4979 bool ValidateGetBufferParameteri64v(const Context *context,
4980 angle::EntryPoint entryPoint,
4981 BufferBinding target,
4982 GLenum pname,
4983 const GLint64 *params)
4984 {
4985 return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
4986 }
4987
ValidateGetSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)4988 bool ValidateGetSamplerParameterfv(const Context *context,
4989 angle::EntryPoint entryPoint,
4990 SamplerID sampler,
4991 GLenum pname,
4992 const GLfloat *params)
4993 {
4994 return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
4995 }
4996
ValidateGetSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)4997 bool ValidateGetSamplerParameteriv(const Context *context,
4998 angle::EntryPoint entryPoint,
4999 SamplerID sampler,
5000 GLenum pname,
5001 const GLint *params)
5002 {
5003 return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
5004 }
5005
ValidateSamplerParameterf(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLfloat param)5006 bool ValidateSamplerParameterf(const Context *context,
5007 angle::EntryPoint entryPoint,
5008 SamplerID sampler,
5009 GLenum pname,
5010 GLfloat param)
5011 {
5012 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, ¶m);
5013 }
5014
ValidateSamplerParameterfv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLfloat * params)5015 bool ValidateSamplerParameterfv(const Context *context,
5016 angle::EntryPoint entryPoint,
5017 SamplerID sampler,
5018 GLenum pname,
5019 const GLfloat *params)
5020 {
5021 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5022 }
5023
ValidateSamplerParameteri(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLint param)5024 bool ValidateSamplerParameteri(const Context *context,
5025 angle::EntryPoint entryPoint,
5026 SamplerID sampler,
5027 GLenum pname,
5028 GLint param)
5029 {
5030 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, ¶m);
5031 }
5032
ValidateSamplerParameteriv(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,const GLint * params)5033 bool ValidateSamplerParameteriv(const Context *context,
5034 angle::EntryPoint entryPoint,
5035 SamplerID sampler,
5036 GLenum pname,
5037 const GLint *params)
5038 {
5039 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
5040 }
5041
ValidateGetVertexAttribIiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLint * params)5042 bool ValidateGetVertexAttribIiv(const Context *context,
5043 angle::EntryPoint entryPoint,
5044 GLuint index,
5045 GLenum pname,
5046 const GLint *params)
5047 {
5048 return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
5049 }
5050
ValidateGetVertexAttribIuiv(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,const GLuint * params)5051 bool ValidateGetVertexAttribIuiv(const Context *context,
5052 angle::EntryPoint entryPoint,
5053 GLuint index,
5054 GLenum pname,
5055 const GLuint *params)
5056 {
5057 return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
5058 }
5059
ValidateGetInternalformativ(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLint * params)5060 bool ValidateGetInternalformativ(const Context *context,
5061 angle::EntryPoint entryPoint,
5062 GLenum target,
5063 GLenum internalformat,
5064 GLenum pname,
5065 GLsizei bufSize,
5066 const GLint *params)
5067 {
5068 return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
5069 bufSize, nullptr);
5070 }
5071
ValidateBindFragDataLocationIndexedEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,GLuint index,const char * name)5072 bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
5073 angle::EntryPoint entryPoint,
5074 ShaderProgramID program,
5075 GLuint colorNumber,
5076 GLuint index,
5077 const char *name)
5078 {
5079 if (!context->getExtensions().blendFuncExtendedEXT)
5080 {
5081 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5082 return false;
5083 }
5084 if (context->getClientMajorVersion() < 3)
5085 {
5086 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5087 return false;
5088 }
5089 if (index > 1)
5090 {
5091 // This error is not explicitly specified but the spec does say that "<index> may be zero or
5092 // one to specify that the color be used as either the first or second color input to the
5093 // blend equation, respectively"
5094 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
5095 return false;
5096 }
5097 if (index == 1)
5098 {
5099 if (colorNumber >= context->getCaps().maxDualSourceDrawBuffers)
5100 {
5101 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE,
5102 kColorNumberGreaterThanMaxDualSourceDrawBuffers);
5103 return false;
5104 }
5105 }
5106 else
5107 {
5108 if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
5109 {
5110 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kColorNumberGreaterThanMaxDrawBuffers);
5111 return false;
5112 }
5113 }
5114 Program *programObject = GetValidProgram(context, entryPoint, program);
5115 if (!programObject)
5116 {
5117 return false;
5118 }
5119 return true;
5120 }
5121
ValidateBindFragDataLocationEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLuint colorNumber,const char * name)5122 bool ValidateBindFragDataLocationEXT(const Context *context,
5123 angle::EntryPoint entryPoint,
5124 ShaderProgramID program,
5125 GLuint colorNumber,
5126 const char *name)
5127 {
5128 return ValidateBindFragDataLocationIndexedEXT(context, entryPoint, program, colorNumber, 0u,
5129 name);
5130 }
5131
ValidateGetFragDataIndexEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,const char * name)5132 bool ValidateGetFragDataIndexEXT(const Context *context,
5133 angle::EntryPoint entryPoint,
5134 ShaderProgramID program,
5135 const char *name)
5136 {
5137 if (!context->getExtensions().blendFuncExtendedEXT)
5138 {
5139 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5140 return false;
5141 }
5142 if (context->getClientMajorVersion() < 3)
5143 {
5144 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
5145 return false;
5146 }
5147 Program *programObject = GetValidProgram(context, entryPoint, program);
5148 if (!programObject)
5149 {
5150 return false;
5151 }
5152 if (!programObject->isLinked())
5153 {
5154 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
5155 return false;
5156 }
5157 return true;
5158 }
5159
ValidateTexStorage2DMultisampleANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)5160 bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
5161 angle::EntryPoint entryPoint,
5162 TextureType target,
5163 GLsizei samples,
5164 GLenum internalFormat,
5165 GLsizei width,
5166 GLsizei height,
5167 GLboolean fixedSampleLocations)
5168 {
5169 if (!context->getExtensions().textureMultisampleANGLE)
5170 {
5171 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
5172 return false;
5173 }
5174
5175 return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
5176 width, height);
5177 }
5178
ValidateGetTexLevelParameterfvANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLfloat * params)5179 bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
5180 angle::EntryPoint entryPoint,
5181 TextureTarget target,
5182 GLint level,
5183 GLenum pname,
5184 const GLfloat *params)
5185 {
5186 if (!context->getExtensions().textureMultisampleANGLE &&
5187 !context->getExtensions().getTexLevelParameterANGLE)
5188 {
5189 ANGLE_VALIDATION_ERROR(
5190 GL_INVALID_OPERATION,
5191 kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5192 return false;
5193 }
5194
5195 return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5196 }
5197
ValidateGetTexLevelParameterivANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,const GLint * params)5198 bool ValidateGetTexLevelParameterivANGLE(const Context *context,
5199 angle::EntryPoint entryPoint,
5200 TextureTarget target,
5201 GLint level,
5202 GLenum pname,
5203 const GLint *params)
5204 {
5205 if (!context->getExtensions().textureMultisampleANGLE &&
5206 !context->getExtensions().getTexLevelParameterANGLE)
5207 {
5208 ANGLE_VALIDATION_ERROR(
5209 GL_INVALID_OPERATION,
5210 kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
5211 return false;
5212 }
5213
5214 return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
5215 }
5216
ValidateGetMultisamplefvANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,const GLfloat * val)5217 bool ValidateGetMultisamplefvANGLE(const Context *context,
5218 angle::EntryPoint entryPoint,
5219 GLenum pname,
5220 GLuint index,
5221 const GLfloat *val)
5222 {
5223 if (!context->getExtensions().textureMultisampleANGLE)
5224 {
5225 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
5226 return false;
5227 }
5228
5229 return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
5230 }
5231
ValidateSampleMaskiANGLE(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint maskNumber,GLbitfield mask)5232 bool ValidateSampleMaskiANGLE(const PrivateState &state,
5233 ErrorSet *errors,
5234 angle::EntryPoint entryPoint,
5235 GLuint maskNumber,
5236 GLbitfield mask)
5237 {
5238 if (!state.getExtensions().textureMultisampleANGLE)
5239 {
5240 errors->validationError(entryPoint, GL_INVALID_OPERATION,
5241 kMultisampleTextureExtensionOrES31Required);
5242 return false;
5243 }
5244
5245 return ValidateSampleMaskiBase(state, errors, entryPoint, maskNumber, mask);
5246 }
5247
ValidateDrawBufferIndexIfActivePLS(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint drawBufferIdx,const char * argumentName)5248 bool ValidateDrawBufferIndexIfActivePLS(const PrivateState &state,
5249 ErrorSet *errors,
5250 angle::EntryPoint entryPoint,
5251 GLuint drawBufferIdx,
5252 const char *argumentName)
5253 {
5254 int numPLSPlanes = state.getPixelLocalStorageActivePlanes();
5255 if (numPLSPlanes != 0)
5256 {
5257 // INVALID_OPERATION is generated ... if any of the following are true:
5258 //
5259 // <drawBufferIdx> >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
5260 // <drawBufferIdx> >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
5261 // ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE)
5262 //
5263 if (drawBufferIdx >= state.getCaps().maxColorAttachmentsWithActivePixelLocalStorage)
5264 {
5265 errors->validationErrorF(entryPoint, GL_INVALID_OPERATION,
5266 kPLSDrawBufferExceedsAttachmentLimit, argumentName);
5267 return false;
5268 }
5269 if (drawBufferIdx >=
5270 state.getCaps().maxCombinedDrawBuffersAndPixelLocalStoragePlanes - numPLSPlanes)
5271 {
5272 errors->validationErrorF(entryPoint, GL_INVALID_OPERATION,
5273 kPLSDrawBufferExceedsCombinedAttachmentLimit, argumentName);
5274 return false;
5275 }
5276 }
5277 return true;
5278 }
5279 } // namespace gl
5280