1 // 2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters 8 9 #include "libGLESv2/validationES2.h" 10 #include "libGLESv2/validationES.h" 11 #include "libGLESv2/Context.h" 12 #include "libGLESv2/Texture.h" 13 #include "libGLESv2/Framebuffer.h" 14 #include "libGLESv2/Renderbuffer.h" 15 #include "libGLESv2/formatutils.h" 16 #include "libGLESv2/main.h" 17 #include "libGLESv2/FramebufferAttachment.h" 18 19 #include "common/mathutil.h" 20 #include "common/utilities.h" 21 22 namespace gl 23 { 24 25 static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height, 26 GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, 27 gl::Texture2D *texture) 28 { 29 if (!texture) 30 { 31 context->recordError(Error(GL_INVALID_OPERATION)); 32 return false; 33 } 34 35 if (compressed != texture->isCompressed(level)) 36 { 37 context->recordError(Error(GL_INVALID_OPERATION)); 38 return false; 39 } 40 41 if (format != GL_NONE) 42 { 43 if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) 44 { 45 context->recordError(Error(GL_INVALID_OPERATION)); 46 return false; 47 } 48 } 49 50 if (compressed) 51 { 52 if ((width % 4 != 0 && width != texture->getWidth(level)) || 53 (height % 4 != 0 && height != texture->getHeight(level))) 54 { 55 context->recordError(Error(GL_INVALID_OPERATION)); 56 return false; 57 } 58 } 59 60 if (xoffset + width > texture->getWidth(level) || 61 yoffset + height > texture->getHeight(level)) 62 { 63 context->recordError(Error(GL_INVALID_VALUE)); 64 return false; 65 } 66 67 return true; 68 } 69 70 static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height, 71 GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, 72 gl::TextureCubeMap *texture) 73 { 74 if (!texture) 75 { 76 context->recordError(Error(GL_INVALID_OPERATION)); 77 return false; 78 } 79 80 if (compressed != texture->isCompressed(target, level)) 81 { 82 context->recordError(Error(GL_INVALID_OPERATION)); 83 return false; 84 } 85 86 if (format != GL_NONE) 87 { 88 if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level)) 89 { 90 context->recordError(Error(GL_INVALID_OPERATION)); 91 return false; 92 } 93 } 94 95 if (compressed) 96 { 97 if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || 98 (height % 4 != 0 && height != texture->getHeight(target, 0))) 99 { 100 context->recordError(Error(GL_INVALID_OPERATION)); 101 return false; 102 } 103 } 104 105 if (xoffset + width > texture->getWidth(target, level) || 106 yoffset + height > texture->getHeight(target, level)) 107 { 108 context->recordError(Error(GL_INVALID_VALUE)); 109 return false; 110 } 111 112 return true; 113 } 114 115 bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, 116 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, 117 GLint border, GLenum format, GLenum type, const GLvoid *pixels) 118 { 119 if (!ValidTexture2DDestinationTarget(context, target)) 120 { 121 context->recordError(Error(GL_INVALID_ENUM)); 122 return false; 123 } 124 125 if (!ValidImageSize(context, target, level, width, height, 1)) 126 { 127 context->recordError(Error(GL_INVALID_VALUE)); 128 return false; 129 } 130 131 if (level < 0 || xoffset < 0 || 132 std::numeric_limits<GLsizei>::max() - xoffset < width || 133 std::numeric_limits<GLsizei>::max() - yoffset < height) 134 { 135 context->recordError(Error(GL_INVALID_VALUE)); 136 return false; 137 } 138 139 if (!isSubImage && !isCompressed && internalformat != format) 140 { 141 context->recordError(Error(GL_INVALID_OPERATION)); 142 return false; 143 } 144 145 const gl::Caps &caps = context->getCaps(); 146 147 gl::Texture *texture = NULL; 148 bool textureCompressed = false; 149 GLenum textureInternalFormat = GL_NONE; 150 GLint textureLevelWidth = 0; 151 GLint textureLevelHeight = 0; 152 switch (target) 153 { 154 case GL_TEXTURE_2D: 155 { 156 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || 157 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) 158 { 159 context->recordError(Error(GL_INVALID_VALUE)); 160 return false; 161 } 162 163 gl::Texture2D *tex2d = context->getTexture2D(); 164 if (tex2d) 165 { 166 textureCompressed = tex2d->isCompressed(level); 167 textureInternalFormat = tex2d->getInternalFormat(level); 168 textureLevelWidth = tex2d->getWidth(level); 169 textureLevelHeight = tex2d->getHeight(level); 170 texture = tex2d; 171 } 172 173 if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset, 174 level, format, type, tex2d)) 175 { 176 return false; 177 } 178 179 texture = tex2d; 180 } 181 break; 182 183 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 184 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 185 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 186 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 187 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 188 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 189 { 190 if (!isSubImage && width != height) 191 { 192 context->recordError(Error(GL_INVALID_VALUE)); 193 return false; 194 } 195 196 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) || 197 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level)) 198 { 199 context->recordError(Error(GL_INVALID_VALUE)); 200 return false; 201 } 202 203 gl::TextureCubeMap *texCube = context->getTextureCubeMap(); 204 if (texCube) 205 { 206 textureCompressed = texCube->isCompressed(target, level); 207 textureInternalFormat = texCube->getInternalFormat(target, level); 208 textureLevelWidth = texCube->getWidth(target, level); 209 textureLevelHeight = texCube->getHeight(target, level); 210 texture = texCube; 211 } 212 213 if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset, 214 target, level, format, type, texCube)) 215 { 216 return false; 217 } 218 } 219 break; 220 221 default: 222 context->recordError(Error(GL_INVALID_ENUM)); 223 return false; 224 } 225 226 if (!texture) 227 { 228 context->recordError(Error(GL_INVALID_OPERATION)); 229 return false; 230 } 231 232 if (!isSubImage && texture->isImmutable()) 233 { 234 context->recordError(Error(GL_INVALID_OPERATION)); 235 return false; 236 } 237 238 // Verify zero border 239 if (border != 0) 240 { 241 context->recordError(Error(GL_INVALID_VALUE)); 242 return false; 243 } 244 245 GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; 246 if (isCompressed) 247 { 248 if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) 249 { 250 context->recordError(Error(GL_INVALID_OPERATION)); 251 return false; 252 } 253 254 switch (actualInternalFormat) 255 { 256 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 257 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 258 if (!context->getExtensions().textureCompressionDXT1) 259 { 260 context->recordError(Error(GL_INVALID_ENUM)); 261 return false; 262 } 263 break; 264 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 265 if (!context->getExtensions().textureCompressionDXT1) 266 { 267 context->recordError(Error(GL_INVALID_ENUM)); 268 return false; 269 } 270 break; 271 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 272 if (!context->getExtensions().textureCompressionDXT5) 273 { 274 context->recordError(Error(GL_INVALID_ENUM)); 275 return false; 276 } 277 break; 278 default: 279 context->recordError(Error(GL_INVALID_ENUM)); 280 return false; 281 } 282 } 283 else 284 { 285 // validate <type> by itself (used as secondary key below) 286 switch (type) 287 { 288 case GL_UNSIGNED_BYTE: 289 case GL_UNSIGNED_SHORT_5_6_5: 290 case GL_UNSIGNED_SHORT_4_4_4_4: 291 case GL_UNSIGNED_SHORT_5_5_5_1: 292 case GL_UNSIGNED_SHORT: 293 case GL_UNSIGNED_INT: 294 case GL_UNSIGNED_INT_24_8_OES: 295 case GL_HALF_FLOAT_OES: 296 case GL_FLOAT: 297 break; 298 default: 299 context->recordError(Error(GL_INVALID_ENUM)); 300 return false; 301 } 302 303 // validate <format> + <type> combinations 304 // - invalid <format> -> sets INVALID_ENUM 305 // - invalid <format>+<type> combination -> sets INVALID_OPERATION 306 switch (format) 307 { 308 case GL_ALPHA: 309 case GL_LUMINANCE: 310 case GL_LUMINANCE_ALPHA: 311 switch (type) 312 { 313 case GL_UNSIGNED_BYTE: 314 case GL_FLOAT: 315 case GL_HALF_FLOAT_OES: 316 break; 317 default: 318 context->recordError(Error(GL_INVALID_OPERATION)); 319 return false; 320 } 321 break; 322 case GL_RED: 323 case GL_RG: 324 if (!context->getExtensions().textureRG) 325 { 326 context->recordError(Error(GL_INVALID_ENUM)); 327 return false; 328 } 329 switch (type) 330 { 331 case GL_UNSIGNED_BYTE: 332 case GL_FLOAT: 333 case GL_HALF_FLOAT_OES: 334 break; 335 default: 336 context->recordError(Error(GL_INVALID_OPERATION)); 337 return false; 338 } 339 break; 340 case GL_RGB: 341 switch (type) 342 { 343 case GL_UNSIGNED_BYTE: 344 case GL_UNSIGNED_SHORT_5_6_5: 345 case GL_FLOAT: 346 case GL_HALF_FLOAT_OES: 347 break; 348 default: 349 context->recordError(Error(GL_INVALID_OPERATION)); 350 return false; 351 } 352 break; 353 case GL_RGBA: 354 switch (type) 355 { 356 case GL_UNSIGNED_BYTE: 357 case GL_UNSIGNED_SHORT_4_4_4_4: 358 case GL_UNSIGNED_SHORT_5_5_5_1: 359 case GL_FLOAT: 360 case GL_HALF_FLOAT_OES: 361 break; 362 default: 363 context->recordError(Error(GL_INVALID_OPERATION)); 364 return false; 365 } 366 break; 367 case GL_BGRA_EXT: 368 switch (type) 369 { 370 case GL_UNSIGNED_BYTE: 371 break; 372 default: 373 context->recordError(Error(GL_INVALID_OPERATION)); 374 return false; 375 } 376 break; 377 case GL_SRGB_EXT: 378 case GL_SRGB_ALPHA_EXT: 379 if (!context->getExtensions().sRGB) 380 { 381 context->recordError(Error(GL_INVALID_ENUM)); 382 return false; 383 } 384 switch (type) 385 { 386 case GL_UNSIGNED_BYTE: 387 break; 388 default: 389 context->recordError(Error(GL_INVALID_OPERATION)); 390 return false; 391 } 392 break; 393 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below 394 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 395 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 396 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 397 break; 398 case GL_DEPTH_COMPONENT: 399 switch (type) 400 { 401 case GL_UNSIGNED_SHORT: 402 case GL_UNSIGNED_INT: 403 break; 404 default: 405 context->recordError(Error(GL_INVALID_OPERATION)); 406 return false; 407 } 408 break; 409 case GL_DEPTH_STENCIL_OES: 410 switch (type) 411 { 412 case GL_UNSIGNED_INT_24_8_OES: 413 break; 414 default: 415 context->recordError(Error(GL_INVALID_OPERATION)); 416 return false; 417 } 418 break; 419 default: 420 context->recordError(Error(GL_INVALID_ENUM)); 421 return false; 422 } 423 424 switch (format) 425 { 426 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 427 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 428 if (context->getExtensions().textureCompressionDXT1) 429 { 430 context->recordError(Error(GL_INVALID_OPERATION)); 431 return false; 432 } 433 else 434 { 435 context->recordError(Error(GL_INVALID_ENUM)); 436 return false; 437 } 438 break; 439 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 440 if (context->getExtensions().textureCompressionDXT3) 441 { 442 context->recordError(Error(GL_INVALID_OPERATION)); 443 return false; 444 } 445 else 446 { 447 context->recordError(Error(GL_INVALID_ENUM)); 448 return false; 449 } 450 break; 451 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 452 if (context->getExtensions().textureCompressionDXT5) 453 { 454 context->recordError(Error(GL_INVALID_OPERATION)); 455 return false; 456 } 457 else 458 { 459 context->recordError(Error(GL_INVALID_ENUM)); 460 return false; 461 } 462 break; 463 case GL_DEPTH_COMPONENT: 464 case GL_DEPTH_STENCIL_OES: 465 if (!context->getExtensions().depthTextures) 466 { 467 context->recordError(Error(GL_INVALID_VALUE)); 468 return false; 469 } 470 if (target != GL_TEXTURE_2D) 471 { 472 context->recordError(Error(GL_INVALID_OPERATION)); 473 return false; 474 } 475 // OES_depth_texture supports loading depth data and multiple levels, 476 // but ANGLE_depth_texture does not 477 if (pixels != NULL || level != 0) 478 { 479 context->recordError(Error(GL_INVALID_OPERATION)); 480 return false; 481 } 482 break; 483 default: 484 break; 485 } 486 487 if (type == GL_FLOAT) 488 { 489 if (!context->getExtensions().textureFloat) 490 { 491 context->recordError(Error(GL_INVALID_ENUM)); 492 return false; 493 } 494 } 495 else if (type == GL_HALF_FLOAT_OES) 496 { 497 if (!context->getExtensions().textureHalfFloat) 498 { 499 context->recordError(Error(GL_INVALID_ENUM)); 500 return false; 501 } 502 } 503 } 504 505 return true; 506 } 507 508 509 510 bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, 511 GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, 512 GLint border) 513 { 514 GLenum textureInternalFormat = GL_NONE; 515 516 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, 517 xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) 518 { 519 return false; 520 } 521 522 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); 523 GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); 524 GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format; 525 526 // [OpenGL ES 2.0.24] table 3.9 527 if (isSubImage) 528 { 529 switch (textureFormat) 530 { 531 case GL_ALPHA: 532 if (colorbufferFormat != GL_ALPHA8_EXT && 533 colorbufferFormat != GL_RGBA4 && 534 colorbufferFormat != GL_RGB5_A1 && 535 colorbufferFormat != GL_RGBA8_OES) 536 { 537 context->recordError(Error(GL_INVALID_OPERATION)); 538 return false; 539 } 540 break; 541 case GL_LUMINANCE: 542 if (colorbufferFormat != GL_R8_EXT && 543 colorbufferFormat != GL_RG8_EXT && 544 colorbufferFormat != GL_RGB565 && 545 colorbufferFormat != GL_RGB8_OES && 546 colorbufferFormat != GL_RGBA4 && 547 colorbufferFormat != GL_RGB5_A1 && 548 colorbufferFormat != GL_RGBA8_OES) 549 { 550 context->recordError(Error(GL_INVALID_OPERATION)); 551 return false; 552 } 553 break; 554 case GL_RED_EXT: 555 if (colorbufferFormat != GL_R8_EXT && 556 colorbufferFormat != GL_RG8_EXT && 557 colorbufferFormat != GL_RGB565 && 558 colorbufferFormat != GL_RGB8_OES && 559 colorbufferFormat != GL_RGBA4 && 560 colorbufferFormat != GL_RGB5_A1 && 561 colorbufferFormat != GL_RGBA8_OES) 562 { 563 context->recordError(Error(GL_INVALID_OPERATION)); 564 return false; 565 } 566 break; 567 case GL_RG_EXT: 568 if (colorbufferFormat != GL_RG8_EXT && 569 colorbufferFormat != GL_RGB565 && 570 colorbufferFormat != GL_RGB8_OES && 571 colorbufferFormat != GL_RGBA4 && 572 colorbufferFormat != GL_RGB5_A1 && 573 colorbufferFormat != GL_RGBA8_OES) 574 { 575 context->recordError(Error(GL_INVALID_OPERATION)); 576 return false; 577 } 578 break; 579 case GL_RGB: 580 if (colorbufferFormat != GL_RGB565 && 581 colorbufferFormat != GL_RGB8_OES && 582 colorbufferFormat != GL_RGBA4 && 583 colorbufferFormat != GL_RGB5_A1 && 584 colorbufferFormat != GL_RGBA8_OES) 585 { 586 context->recordError(Error(GL_INVALID_OPERATION)); 587 return false; 588 } 589 break; 590 case GL_LUMINANCE_ALPHA: 591 case GL_RGBA: 592 if (colorbufferFormat != GL_RGBA4 && 593 colorbufferFormat != GL_RGB5_A1 && 594 colorbufferFormat != GL_RGBA8_OES) 595 { 596 context->recordError(Error(GL_INVALID_OPERATION)); 597 return false; 598 } 599 break; 600 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 601 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 602 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 603 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 604 context->recordError(Error(GL_INVALID_OPERATION)); 605 return false; 606 case GL_DEPTH_COMPONENT: 607 case GL_DEPTH_STENCIL_OES: 608 context->recordError(Error(GL_INVALID_OPERATION)); 609 return false; 610 default: 611 context->recordError(Error(GL_INVALID_OPERATION)); 612 return false; 613 } 614 } 615 else 616 { 617 switch (internalformat) 618 { 619 case GL_ALPHA: 620 if (colorbufferFormat != GL_ALPHA8_EXT && 621 colorbufferFormat != GL_RGBA4 && 622 colorbufferFormat != GL_RGB5_A1 && 623 colorbufferFormat != GL_BGRA8_EXT && 624 colorbufferFormat != GL_RGBA8_OES) 625 { 626 context->recordError(Error(GL_INVALID_OPERATION)); 627 return false; 628 } 629 break; 630 case GL_LUMINANCE: 631 if (colorbufferFormat != GL_R8_EXT && 632 colorbufferFormat != GL_RG8_EXT && 633 colorbufferFormat != GL_RGB565 && 634 colorbufferFormat != GL_RGB8_OES && 635 colorbufferFormat != GL_RGBA4 && 636 colorbufferFormat != GL_RGB5_A1 && 637 colorbufferFormat != GL_BGRA8_EXT && 638 colorbufferFormat != GL_RGBA8_OES) 639 { 640 context->recordError(Error(GL_INVALID_OPERATION)); 641 return false; 642 } 643 break; 644 case GL_RED_EXT: 645 if (colorbufferFormat != GL_R8_EXT && 646 colorbufferFormat != GL_RG8_EXT && 647 colorbufferFormat != GL_RGB565 && 648 colorbufferFormat != GL_RGB8_OES && 649 colorbufferFormat != GL_RGBA4 && 650 colorbufferFormat != GL_RGB5_A1 && 651 colorbufferFormat != GL_BGRA8_EXT && 652 colorbufferFormat != GL_RGBA8_OES) 653 { 654 context->recordError(Error(GL_INVALID_OPERATION)); 655 return false; 656 } 657 break; 658 case GL_RG_EXT: 659 if (colorbufferFormat != GL_RG8_EXT && 660 colorbufferFormat != GL_RGB565 && 661 colorbufferFormat != GL_RGB8_OES && 662 colorbufferFormat != GL_RGBA4 && 663 colorbufferFormat != GL_RGB5_A1 && 664 colorbufferFormat != GL_BGRA8_EXT && 665 colorbufferFormat != GL_RGBA8_OES) 666 { 667 context->recordError(Error(GL_INVALID_OPERATION)); 668 return false; 669 } 670 break; 671 case GL_RGB: 672 if (colorbufferFormat != GL_RGB565 && 673 colorbufferFormat != GL_RGB8_OES && 674 colorbufferFormat != GL_RGBA4 && 675 colorbufferFormat != GL_RGB5_A1 && 676 colorbufferFormat != GL_BGRA8_EXT && 677 colorbufferFormat != GL_RGBA8_OES) 678 { 679 context->recordError(Error(GL_INVALID_OPERATION)); 680 return false; 681 } 682 break; 683 case GL_LUMINANCE_ALPHA: 684 case GL_RGBA: 685 if (colorbufferFormat != GL_RGBA4 && 686 colorbufferFormat != GL_RGB5_A1 && 687 colorbufferFormat != GL_BGRA8_EXT && 688 colorbufferFormat != GL_RGBA8_OES) 689 { 690 context->recordError(Error(GL_INVALID_OPERATION)); 691 return false; 692 } 693 break; 694 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 695 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 696 if (context->getExtensions().textureCompressionDXT1) 697 { 698 context->recordError(Error(GL_INVALID_OPERATION)); 699 return false; 700 } 701 else 702 { 703 context->recordError(Error(GL_INVALID_ENUM)); 704 return false; 705 } 706 break; 707 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 708 if (context->getExtensions().textureCompressionDXT3) 709 { 710 context->recordError(Error(GL_INVALID_OPERATION)); 711 return false; 712 } 713 else 714 { 715 context->recordError(Error(GL_INVALID_ENUM)); 716 return false; 717 } 718 break; 719 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 720 if (context->getExtensions().textureCompressionDXT5) 721 { 722 context->recordError(Error(GL_INVALID_OPERATION)); 723 return false; 724 } 725 else 726 { 727 context->recordError(Error(GL_INVALID_ENUM)); 728 return false; 729 } 730 break; 731 case GL_DEPTH_COMPONENT: 732 case GL_DEPTH_COMPONENT16: 733 case GL_DEPTH_COMPONENT32_OES: 734 case GL_DEPTH_STENCIL_OES: 735 case GL_DEPTH24_STENCIL8_OES: 736 if (context->getExtensions().depthTextures) 737 { 738 context->recordError(Error(GL_INVALID_OPERATION)); 739 return false; 740 } 741 else 742 { 743 context->recordError(Error(GL_INVALID_ENUM)); 744 return false; 745 } 746 default: 747 context->recordError(Error(GL_INVALID_ENUM)); 748 return false; 749 } 750 } 751 752 // If width or height is zero, it is a no-op. Return false without setting an error. 753 return (width > 0 && height > 0); 754 } 755 756 bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, 757 GLsizei width, GLsizei height) 758 { 759 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) 760 { 761 context->recordError(Error(GL_INVALID_ENUM)); 762 return false; 763 } 764 765 if (width < 1 || height < 1 || levels < 1) 766 { 767 context->recordError(Error(GL_INVALID_VALUE)); 768 return false; 769 } 770 771 if (target == GL_TEXTURE_CUBE_MAP && width != height) 772 { 773 context->recordError(Error(GL_INVALID_VALUE)); 774 return false; 775 } 776 777 if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) 778 { 779 context->recordError(Error(GL_INVALID_OPERATION)); 780 return false; 781 } 782 783 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); 784 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) 785 { 786 context->recordError(Error(GL_INVALID_ENUM)); 787 return false; 788 } 789 790 const gl::Caps &caps = context->getCaps(); 791 792 switch (target) 793 { 794 case GL_TEXTURE_2D: 795 if (static_cast<GLuint>(width) > caps.max2DTextureSize || 796 static_cast<GLuint>(height) > caps.max2DTextureSize) 797 { 798 context->recordError(Error(GL_INVALID_VALUE)); 799 return false; 800 } 801 break; 802 case GL_TEXTURE_CUBE_MAP: 803 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize || 804 static_cast<GLuint>(height) > caps.maxCubeMapTextureSize) 805 { 806 context->recordError(Error(GL_INVALID_VALUE)); 807 return false; 808 } 809 break; 810 default: 811 context->recordError(Error(GL_INVALID_ENUM)); 812 return false; 813 } 814 815 if (levels != 1 && !context->getExtensions().textureNPOT) 816 { 817 if (!gl::isPow2(width) || !gl::isPow2(height)) 818 { 819 context->recordError(Error(GL_INVALID_OPERATION)); 820 return false; 821 } 822 } 823 824 switch (internalformat) 825 { 826 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 827 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 828 if (!context->getExtensions().textureCompressionDXT1) 829 { 830 context->recordError(Error(GL_INVALID_ENUM)); 831 return false; 832 } 833 break; 834 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 835 if (!context->getExtensions().textureCompressionDXT3) 836 { 837 context->recordError(Error(GL_INVALID_ENUM)); 838 return false; 839 } 840 break; 841 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 842 if (!context->getExtensions().textureCompressionDXT5) 843 { 844 context->recordError(Error(GL_INVALID_ENUM)); 845 return false; 846 } 847 break; 848 case GL_RGBA32F_EXT: 849 case GL_RGB32F_EXT: 850 case GL_ALPHA32F_EXT: 851 case GL_LUMINANCE32F_EXT: 852 case GL_LUMINANCE_ALPHA32F_EXT: 853 if (!context->getExtensions().textureFloat) 854 { 855 context->recordError(Error(GL_INVALID_ENUM)); 856 return false; 857 } 858 break; 859 case GL_RGBA16F_EXT: 860 case GL_RGB16F_EXT: 861 case GL_ALPHA16F_EXT: 862 case GL_LUMINANCE16F_EXT: 863 case GL_LUMINANCE_ALPHA16F_EXT: 864 if (!context->getExtensions().textureHalfFloat) 865 { 866 context->recordError(Error(GL_INVALID_ENUM)); 867 return false; 868 } 869 break; 870 case GL_R8_EXT: 871 case GL_RG8_EXT: 872 case GL_R16F_EXT: 873 case GL_RG16F_EXT: 874 case GL_R32F_EXT: 875 case GL_RG32F_EXT: 876 if (!context->getExtensions().textureRG) 877 { 878 context->recordError(Error(GL_INVALID_ENUM)); 879 return false; 880 } 881 break; 882 case GL_DEPTH_COMPONENT16: 883 case GL_DEPTH_COMPONENT32_OES: 884 case GL_DEPTH24_STENCIL8_OES: 885 if (!context->getExtensions().depthTextures) 886 { 887 context->recordError(Error(GL_INVALID_ENUM)); 888 return false; 889 } 890 if (target != GL_TEXTURE_2D) 891 { 892 context->recordError(Error(GL_INVALID_OPERATION)); 893 return false; 894 } 895 // ANGLE_depth_texture only supports 1-level textures 896 if (levels != 1) 897 { 898 context->recordError(Error(GL_INVALID_OPERATION)); 899 return false; 900 } 901 break; 902 default: 903 break; 904 } 905 906 gl::Texture *texture = NULL; 907 switch(target) 908 { 909 case GL_TEXTURE_2D: 910 texture = context->getTexture2D(); 911 break; 912 case GL_TEXTURE_CUBE_MAP: 913 texture = context->getTextureCubeMap(); 914 break; 915 default: 916 UNREACHABLE(); 917 } 918 919 if (!texture || texture->id() == 0) 920 { 921 context->recordError(Error(GL_INVALID_OPERATION)); 922 return false; 923 } 924 925 if (texture->isImmutable()) 926 { 927 context->recordError(Error(GL_INVALID_OPERATION)); 928 return false; 929 } 930 931 return true; 932 } 933 934 // check for combinations of format and type that are valid for ReadPixels 935 bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) 936 { 937 switch (format) 938 { 939 case GL_RGBA: 940 switch (type) 941 { 942 case GL_UNSIGNED_BYTE: 943 break; 944 default: 945 return false; 946 } 947 break; 948 case GL_BGRA_EXT: 949 switch (type) 950 { 951 case GL_UNSIGNED_BYTE: 952 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: 953 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: 954 break; 955 default: 956 return false; 957 } 958 break; 959 case GL_RG_EXT: 960 case GL_RED_EXT: 961 if (!context->getExtensions().textureRG) 962 { 963 return false; 964 } 965 switch (type) 966 { 967 case GL_UNSIGNED_BYTE: 968 break; 969 default: 970 return false; 971 } 972 break; 973 974 default: 975 return false; 976 } 977 return true; 978 } 979 980 } 981