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