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