1 /****************************************************************************** 2 3 @File OGLES3/PVRTTextureAPI.cpp 4 5 @Title OGLES3/PVRTTextureAPI 6 7 @Version 8 9 @Copyright Copyright (c) Imagination Technologies Limited. 10 11 @Platform ANSI compatible 12 13 @Description OGLES3 texture loading. 14 15 ******************************************************************************/ 16 17 #include <string.h> 18 #include <stdlib.h> 19 20 #include "PVRTContext.h" 21 #include "PVRTgles3Ext.h" 22 #include "PVRTTexture.h" 23 #include "PVRTTextureAPI.h" 24 #include "PVRTDecompress.h" 25 #include "PVRTFixedPoint.h" 26 #include "PVRTMap.h" 27 #include "PVRTMatrix.h" 28 #include "PVRTMisc.h" 29 #include "PVRTResourceFile.h" 30 31 /***************************************************************************** 32 ** Functions 33 ****************************************************************************/ 34 35 /*!*********************************************************************** 36 @Function: PVRTGetOGLES3TextureFormat 37 @Input: sTextureHeader 38 @Modified: glInternalFormat 39 @Modified: glFormat 40 @Modified: glType 41 @Description: Gets the OpenGLES equivalent values of internal format, 42 format and type for this texture header. This will return 43 any supported OpenGLES texture values, it is up to the user 44 to decide if these are valid for their current platform. 45 *************************************************************************/ 46 static const void PVRTGetOGLES3TextureFormat(const PVRTextureHeaderV3& sTextureHeader, PVRTuint32& glInternalFormat, PVRTuint32& glFormat, PVRTuint32& glType) 47 { 48 PVRTuint64 PixelFormat = sTextureHeader.u64PixelFormat; 49 EPVRTVariableType ChannelType = (EPVRTVariableType)sTextureHeader.u32ChannelType; 50 EPVRTColourSpace ColourSpace = (EPVRTColourSpace)sTextureHeader.u32ColourSpace; 51 52 //Initialisation. Any invalid formats will return 0 always. 53 glFormat = 0; 54 glType = 0; 55 glInternalFormat=0; 56 57 //Get the last 32 bits of the pixel format. 58 PVRTuint64 PixelFormatPartHigh = PixelFormat&PVRTEX_PFHIGHMASK; 59 60 //Check for a compressed format (The first 8 bytes will be 0, so the whole thing will be equal to the last 32 bits). 61 if (PixelFormatPartHigh==0) 62 { 63 //Format and type == 0 for compressed textures. 64 switch (PixelFormat) 65 { 66 case ePVRTPF_PVRTCI_2bpp_RGB: 67 { 68 if (ColourSpace == ePVRTCSpacesRGB) 69 { 70 //glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT; 71 } 72 else 73 { 74 glInternalFormat=GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 75 } 76 return; 77 } 78 case ePVRTPF_PVRTCI_2bpp_RGBA: 79 { 80 if (ColourSpace == ePVRTCSpacesRGB) 81 { 82 //glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; 83 } 84 else 85 { 86 glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 87 } 88 return; 89 } 90 case ePVRTPF_PVRTCI_4bpp_RGB: 91 { 92 if (ColourSpace == ePVRTCSpacesRGB) 93 { 94 //glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT; 95 } 96 else 97 { 98 glInternalFormat=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 99 } 100 return; 101 } 102 case ePVRTPF_PVRTCI_4bpp_RGBA: 103 { 104 if (ColourSpace == ePVRTCSpacesRGB) 105 { 106 //glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; 107 } 108 else 109 { 110 glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 111 } 112 return; 113 } 114 #ifndef TARGET_OS_IPHONE 115 case ePVRTPF_PVRTCII_2bpp: 116 { 117 if (ColourSpace == ePVRTCSpacesRGB) 118 { 119 //glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG; 120 } 121 else 122 { 123 glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG; 124 } 125 return; 126 } 127 case ePVRTPF_PVRTCII_4bpp: 128 { 129 if (ColourSpace == ePVRTCSpacesRGB) 130 { 131 //glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG; 132 } 133 else 134 { 135 glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG; 136 } 137 return; 138 } 139 case ePVRTPF_ETC1: 140 { 141 glInternalFormat=GL_ETC1_RGB8_OES; 142 return; 143 } 144 #endif 145 case ePVRTPF_ETC2_RGB: 146 { 147 if (ColourSpace==ePVRTCSpacesRGB) 148 glInternalFormat=GL_COMPRESSED_SRGB8_ETC2; 149 else 150 glInternalFormat=GL_COMPRESSED_RGB8_ETC2; 151 return; 152 } 153 case ePVRTPF_ETC2_RGBA: 154 { 155 if (ColourSpace==ePVRTCSpacesRGB) 156 glInternalFormat=GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; 157 else 158 glInternalFormat=GL_COMPRESSED_RGBA8_ETC2_EAC; 159 return; 160 } 161 case ePVRTPF_ETC2_RGB_A1: 162 { 163 if (ColourSpace==ePVRTCSpacesRGB) 164 glInternalFormat=GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; 165 else 166 glInternalFormat=GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; 167 return; 168 } 169 case ePVRTPF_EAC_R11: 170 { 171 if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm || 172 ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm || 173 ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm || 174 ChannelType==ePVRTVarTypeSignedFloat) 175 { 176 glInternalFormat=GL_COMPRESSED_SIGNED_R11_EAC; 177 } 178 else 179 { 180 glInternalFormat=GL_COMPRESSED_R11_EAC; 181 } 182 return; 183 } 184 case ePVRTPF_EAC_RG11: 185 { 186 if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm || 187 ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm || 188 ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm || 189 ChannelType==ePVRTVarTypeSignedFloat) 190 { 191 glInternalFormat=GL_COMPRESSED_SIGNED_RG11_EAC; 192 } 193 else 194 { 195 glInternalFormat=GL_COMPRESSED_RG11_EAC; 196 } 197 return; 198 } 199 } 200 } 201 else 202 { 203 switch (ChannelType) 204 { 205 case ePVRTVarTypeUnsignedFloat: 206 if (PixelFormat==PVRTGENPIXELID3('r','g','b',11,11,10) ) 207 { 208 glType=GL_UNSIGNED_INT_10F_11F_11F_REV; 209 glFormat = GL_RGB; 210 glInternalFormat=GL_R11F_G11F_B10F; 211 return; 212 } 213 break; 214 case ePVRTVarTypeSignedFloat: 215 { 216 switch (PixelFormat) 217 { 218 //HALF_FLOAT 219 case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): 220 { 221 glType=GL_HALF_FLOAT; 222 glFormat = GL_RGBA; 223 glInternalFormat=GL_RGBA; 224 return; 225 } 226 case PVRTGENPIXELID3('r','g','b',16,16,16): 227 { 228 glType=GL_HALF_FLOAT; 229 glFormat = GL_RGB; 230 glInternalFormat=GL_RGB16F; 231 return; 232 } 233 case PVRTGENPIXELID2('r','g',16,16): 234 { 235 glType=GL_HALF_FLOAT; 236 glFormat = GL_RG; 237 glInternalFormat=GL_RG16F; 238 return; 239 } 240 case PVRTGENPIXELID1('r',16): 241 { 242 glType=GL_HALF_FLOAT; 243 glFormat = GL_RED; 244 glInternalFormat=GL_R16F; 245 return; 246 } 247 case PVRTGENPIXELID2('l','a',16,16): 248 { 249 glType=GL_HALF_FLOAT; 250 glFormat = GL_LUMINANCE_ALPHA; 251 glInternalFormat=GL_LUMINANCE_ALPHA; 252 return; 253 } 254 case PVRTGENPIXELID1('l',16): 255 { 256 glType=GL_HALF_FLOAT; 257 glFormat = GL_LUMINANCE; 258 glInternalFormat=GL_LUMINANCE; 259 return; 260 } 261 case PVRTGENPIXELID1('a',16): 262 { 263 glType=GL_HALF_FLOAT; 264 glFormat = GL_ALPHA; 265 glInternalFormat=GL_ALPHA; 266 return; 267 } 268 //FLOAT 269 case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): 270 { 271 glType=GL_FLOAT; 272 glFormat = GL_RGBA; 273 glInternalFormat=GL_RGBA32F; 274 return; 275 } 276 case PVRTGENPIXELID3('r','g','b',32,32,32): 277 { 278 glType=GL_FLOAT; 279 glFormat = GL_RGB; 280 glInternalFormat=GL_RGB32F; 281 return; 282 } 283 case PVRTGENPIXELID2('r','g',32,32): 284 { 285 glType=GL_FLOAT; 286 glFormat = GL_RG; 287 glInternalFormat=GL_RG32F; 288 return; 289 } 290 case PVRTGENPIXELID1('r',32): 291 { 292 glType=GL_FLOAT; 293 glFormat = GL_RED; 294 glInternalFormat=GL_R32F; 295 return; 296 } 297 case PVRTGENPIXELID2('l','a',32,32): 298 { 299 glType=GL_FLOAT; 300 glFormat = GL_LUMINANCE_ALPHA; 301 glInternalFormat=GL_LUMINANCE_ALPHA; 302 return; 303 } 304 case PVRTGENPIXELID1('l',32): 305 { 306 glType=GL_FLOAT; 307 glFormat = GL_LUMINANCE; 308 glInternalFormat=GL_LUMINANCE; 309 return; 310 } 311 case PVRTGENPIXELID1('a',32): 312 { 313 glType=GL_FLOAT; 314 glFormat = GL_ALPHA; 315 glInternalFormat=GL_ALPHA; 316 return; 317 } 318 } 319 break; 320 } 321 case ePVRTVarTypeUnsignedByteNorm: 322 { 323 glType = GL_UNSIGNED_BYTE; 324 switch (PixelFormat) 325 { 326 case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): 327 { 328 glFormat = GL_RGBA; 329 if (ColourSpace==ePVRTCSpacesRGB) 330 glInternalFormat=GL_SRGB8_ALPHA8; 331 else 332 glInternalFormat=GL_RGBA8; 333 return; 334 } 335 case PVRTGENPIXELID3('r','g','b',8,8,8): 336 { 337 glFormat = GL_RGB; 338 if (ColourSpace==ePVRTCSpacesRGB) 339 glInternalFormat=GL_SRGB8; 340 else 341 glInternalFormat=GL_RGB8; 342 return; 343 } 344 case PVRTGENPIXELID2('r','g',8,8): 345 { 346 glFormat = GL_RG; 347 glInternalFormat=GL_RG8; 348 return; 349 } 350 case PVRTGENPIXELID1('r',8): 351 { 352 glFormat = GL_RED; 353 glInternalFormat=GL_R8; 354 return; 355 } 356 case PVRTGENPIXELID2('l','a',8,8): 357 { 358 glFormat = GL_LUMINANCE_ALPHA; 359 glInternalFormat=GL_LUMINANCE_ALPHA; 360 return; 361 } 362 case PVRTGENPIXELID1('l',8): 363 { 364 glFormat = GL_LUMINANCE; 365 glInternalFormat=GL_LUMINANCE; 366 return; 367 } 368 case PVRTGENPIXELID1('a',8): 369 { 370 glFormat = GL_ALPHA; 371 glInternalFormat=GL_ALPHA; 372 return; 373 } 374 case PVRTGENPIXELID4('b','g','r','a',8,8,8,8): 375 { 376 glFormat = GL_BGRA_EXT; 377 glInternalFormat=GL_BGRA_EXT; 378 return; 379 } 380 } 381 break; 382 } 383 case ePVRTVarTypeSignedByteNorm: 384 { 385 glType = GL_BYTE; 386 switch (PixelFormat) 387 { 388 case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): 389 { 390 glFormat = GL_RGBA; 391 glInternalFormat=GL_RGBA8_SNORM; 392 return; 393 } 394 case PVRTGENPIXELID3('r','g','b',8,8,8): 395 { 396 glFormat = GL_RGB; 397 glInternalFormat=GL_RGB8_SNORM; 398 return; 399 } 400 case PVRTGENPIXELID2('r','g',8,8): 401 { 402 glFormat = GL_RG; 403 glInternalFormat=GL_RGB8_SNORM; 404 return; 405 } 406 case PVRTGENPIXELID1('r',8): 407 { 408 glFormat = GL_RED; 409 glInternalFormat=GL_R8_SNORM; 410 return; 411 } 412 } 413 break; 414 } 415 case ePVRTVarTypeUnsignedByte: 416 { 417 glType = GL_UNSIGNED_BYTE; 418 switch (PixelFormat) 419 { 420 case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): 421 { 422 glFormat = GL_RGBA_INTEGER; 423 glInternalFormat=GL_RGBA8UI; 424 return; 425 } 426 case PVRTGENPIXELID3('r','g','b',8,8,8): 427 { 428 glFormat = GL_RGB_INTEGER; 429 glInternalFormat=GL_RGB8UI; 430 return; 431 } 432 case PVRTGENPIXELID2('r','g',8,8): 433 { 434 glFormat = GL_RG_INTEGER; 435 glInternalFormat=GL_RG8UI; 436 return; 437 } 438 case PVRTGENPIXELID1('r',8): 439 { 440 glFormat = GL_RED_INTEGER; 441 glInternalFormat=GL_R8UI; 442 return; 443 } 444 } 445 break; 446 } 447 case ePVRTVarTypeSignedByte: 448 { 449 glType = GL_BYTE; 450 switch (PixelFormat) 451 { 452 case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): 453 { 454 glFormat = GL_RGBA_INTEGER; 455 glInternalFormat=GL_RGBA8I; 456 return; 457 } 458 case PVRTGENPIXELID3('r','g','b',8,8,8): 459 { 460 glFormat = GL_RGB_INTEGER; 461 glInternalFormat=GL_RGB8I; 462 return; 463 } 464 case PVRTGENPIXELID2('r','g',8,8): 465 { 466 glFormat = GL_RG_INTEGER; 467 glInternalFormat=GL_RG8I; 468 return; 469 } 470 case PVRTGENPIXELID1('r',8): 471 { 472 glFormat = GL_RED_INTEGER; 473 glInternalFormat=GL_R8I; 474 return; 475 } 476 } 477 break; 478 } 479 case ePVRTVarTypeUnsignedShortNorm: 480 { 481 switch (PixelFormat) 482 { 483 case PVRTGENPIXELID4('r','g','b','a',4,4,4,4): 484 { 485 glType = GL_UNSIGNED_SHORT_4_4_4_4; 486 glFormat = GL_RGBA; 487 glInternalFormat=GL_RGBA4; 488 return; 489 } 490 case PVRTGENPIXELID4('r','g','b','a',5,5,5,1): 491 { 492 glType = GL_UNSIGNED_SHORT_5_5_5_1; 493 glFormat = GL_RGBA; 494 glInternalFormat=GL_RGB5_A1; 495 return; 496 } 497 case PVRTGENPIXELID3('r','g','b',5,6,5): 498 { 499 glType = GL_UNSIGNED_SHORT_5_6_5; 500 glFormat = GL_RGB; 501 glInternalFormat=GL_RGB565; 502 return; 503 } 504 } 505 break; 506 } 507 case ePVRTVarTypeUnsignedShort: 508 { 509 glType = GL_UNSIGNED_SHORT; 510 switch (PixelFormat) 511 { 512 case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): 513 { 514 glFormat = GL_RGBA_INTEGER; 515 glInternalFormat=GL_RGBA16UI; 516 return; 517 } 518 case PVRTGENPIXELID3('r','g','b',16,16,16): 519 { 520 glFormat = GL_RGB_INTEGER; 521 glInternalFormat=GL_RGB16UI; 522 return; 523 } 524 case PVRTGENPIXELID2('r','g',16,16): 525 { 526 glFormat = GL_RG_INTEGER; 527 glInternalFormat=GL_RG16UI; 528 return; 529 } 530 case PVRTGENPIXELID1('r',16): 531 { 532 glFormat = GL_RED_INTEGER; 533 glInternalFormat=GL_R16UI; 534 return; 535 } 536 } 537 break; 538 } 539 case ePVRTVarTypeSignedShort: 540 { 541 glType = GL_SHORT; 542 switch (PixelFormat) 543 { 544 case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): 545 { 546 glFormat = GL_RGBA_INTEGER; 547 glInternalFormat=GL_RGBA16I; 548 return; 549 } 550 case PVRTGENPIXELID3('r','g','b',16,16,16): 551 { 552 glFormat = GL_RGB_INTEGER; 553 glInternalFormat=GL_RGB16I; 554 return; 555 } 556 case PVRTGENPIXELID2('r','g',16,16): 557 { 558 glFormat = GL_RG_INTEGER; 559 glInternalFormat=GL_RG16I; 560 return; 561 } 562 case PVRTGENPIXELID1('r',16): 563 { 564 glFormat = GL_RED_INTEGER; 565 glInternalFormat=GL_R16I; 566 return; 567 } 568 } 569 break; 570 } 571 case ePVRTVarTypeUnsignedIntegerNorm: 572 { 573 if (PixelFormat==PVRTGENPIXELID4('a','b','g','r',2,10,10,10)) 574 { 575 glType = GL_UNSIGNED_INT_2_10_10_10_REV; 576 glFormat = GL_RGBA; 577 glInternalFormat=GL_RGB10_A2; 578 return; 579 } 580 break; 581 } 582 case ePVRTVarTypeUnsignedInteger: 583 { 584 glType = GL_UNSIGNED_INT; 585 switch (PixelFormat) 586 { 587 case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): 588 { 589 glFormat = GL_RGBA_INTEGER; 590 glInternalFormat=GL_RGBA32UI; 591 return; 592 } 593 case PVRTGENPIXELID3('r','g','b',32,32,32): 594 { 595 glFormat = GL_RGB_INTEGER; 596 glInternalFormat=GL_RGB32UI; 597 return; 598 } 599 case PVRTGENPIXELID2('r','g',32,32): 600 { 601 glFormat = GL_RG_INTEGER; 602 glInternalFormat=GL_RG32UI; 603 return; 604 } 605 case PVRTGENPIXELID1('r',32): 606 { 607 glFormat = GL_RED_INTEGER; 608 glInternalFormat=GL_R32UI; 609 return; 610 } 611 case PVRTGENPIXELID4('a','b','g','r',2,10,10,10): 612 { 613 glType = GL_UNSIGNED_INT_2_10_10_10_REV; 614 glFormat = GL_RGBA_INTEGER; 615 glInternalFormat=GL_RGB10_A2UI; 616 return; 617 } 618 } 619 break; 620 } 621 case ePVRTVarTypeSignedInteger: 622 { 623 glType = GL_INT; 624 switch (PixelFormat) 625 { 626 case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): 627 { 628 glFormat = GL_RGBA_INTEGER; 629 glInternalFormat=GL_RGBA32I; 630 return; 631 } 632 case PVRTGENPIXELID3('r','g','b',32,32,32): 633 { 634 glFormat = GL_RGB_INTEGER; 635 glInternalFormat=GL_RGB32I; 636 return; 637 } 638 case PVRTGENPIXELID2('r','g',32,32): 639 { 640 glFormat = GL_RG_INTEGER; 641 glInternalFormat=GL_RG32I; 642 return; 643 } 644 case PVRTGENPIXELID1('r',32): 645 { 646 glFormat = GL_RED_INTEGER; 647 glInternalFormat=GL_R32I; 648 return; 649 } 650 } 651 break; 652 } 653 default: { } 654 } 655 } 656 657 //Default (erroneous) return values. 658 glType = glFormat = glInternalFormat = 0; 659 } 660 661 662 /*!*************************************************************************** 663 @Function PVRTTextureTile 664 @Modified pOut The tiled texture in system memory 665 @Input pIn The source texture 666 @Input nRepeatCnt Number of times to repeat the source texture 667 @Description Allocates and fills, in system memory, a texture large enough 668 to repeat the source texture specified number of times. 669 *****************************************************************************/ 670 void PVRTTextureTile( 671 PVRTextureHeaderV3 **pOut, 672 const PVRTextureHeaderV3 * const pIn, 673 const int nRepeatCnt) 674 { 675 unsigned int nFormat = 0, nType = 0, nBPP, nSize, nElW = 0, nElH = 0, nElD = 0; 676 PVRTuint8 *pMmSrc, *pMmDst; 677 unsigned int nLevel; 678 PVRTextureHeaderV3 *psTexHeaderNew; 679 680 _ASSERT(pIn->u32Width); 681 _ASSERT(pIn->u32Width == pIn->u32Height); 682 _ASSERT(nRepeatCnt > 1); 683 684 PVRTGetOGLES3TextureFormat(*pIn,nFormat,nFormat,nType); 685 PVRTGetFormatMinDims(pIn->u64PixelFormat,nElW,nElH,nElD); 686 687 nBPP = PVRTGetBitsPerPixel(pIn->u64PixelFormat); 688 nSize = pIn->u32Width * nRepeatCnt; 689 690 psTexHeaderNew = PVRTTextureCreate(nSize, nSize, nElW, nElH, nBPP, true); 691 *psTexHeaderNew = *pIn; 692 pMmDst = (PVRTuint8*)psTexHeaderNew + sizeof(*psTexHeaderNew); 693 pMmSrc = (PVRTuint8*)pIn + sizeof(*pIn); 694 695 for(nLevel = 0; ((unsigned int)1 << nLevel) < nSize; ++nLevel) 696 { 697 int nBlocksDstW = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElW); 698 int nBlocksDstH = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElH); 699 int nBlocksSrcW = PVRT_MAX((unsigned int)1, (pIn->u32Width >> nLevel) / nElW); 700 int nBlocksSrcH = PVRT_MAX((unsigned int)1, (pIn->u32Height >> nLevel) / nElH); 701 int nBlocksS = nBPP * nElW * nElH / 8; 702 703 PVRTTextureLoadTiled( 704 pMmDst, 705 nBlocksDstW, 706 nBlocksDstH, 707 pMmSrc, 708 nBlocksSrcW, 709 nBlocksSrcH, 710 nBlocksS, 711 (pIn->u64PixelFormat>=ePVRTPF_PVRTCI_2bpp_RGB && pIn->u64PixelFormat<=ePVRTPF_PVRTCI_4bpp_RGBA) ? true : false); 712 713 pMmDst += nBlocksDstW * nBlocksDstH * nBlocksS; 714 pMmSrc += nBlocksSrcW * nBlocksSrcH * nBlocksS; 715 } 716 717 psTexHeaderNew->u32Width = nSize; 718 psTexHeaderNew->u32Height = nSize; 719 psTexHeaderNew->u32MIPMapCount = nLevel+1; 720 *pOut = psTexHeaderNew; 721 } 722 723 /*!*************************************************************************** 724 @Function PVRTTextureLoadFromPointer 725 @Input pointer Pointer to header-texture's structure 726 @Modified texName the OpenGL ES texture name as returned by glBindTexture 727 @Modified psTextureHeader Pointer to a PVRTextureHeaderV3 struct. Modified to 728 contain the header data of the returned texture Ignored if NULL. 729 @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware. 730 @Input nLoadFromLevel Which mip map level to start loading from (0=all) 731 @Input texPtr If null, texture follows header, else texture is here. 732 @Modified pMetaData If a valid map is supplied, this will return any and all 733 MetaDataBlocks stored in the texture, organised by DevFourCC 734 then identifier. Supplying NULL will ignore all MetaData. 735 @Return PVR_SUCCESS on success 736 @Description Allows textures to be stored in C header files and loaded in. Can load parts of a 737 mip mapped texture (i.e. skipping the highest detailed levels). In OpenGL Cube Map, each 738 texture's up direction is defined as next (view direction, up direction), 739 (+x,-y)(-x,-y)(+y,+z)(-y,-z)(+z,-y)(-z,-y). 740 Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR 741 if mip maps are present, GL_LINEAR/GL_LINEAR otherwise. 742 *****************************************************************************/ 743 EPVRTError PVRTTextureLoadFromPointer( const void* pointer, 744 GLuint *const texName, 745 const void *psTextureHeader, 746 bool bAllowDecompress, 747 const unsigned int nLoadFromLevel, 748 const void * const texPtr, 749 CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData) 750 { 751 //Compression bools 752 bool bIsCompressedFormatSupported=false; 753 bool bIsCompressedFormat=false; 754 bool bIsLegacyPVR=false; 755 bool bUsesTexImage3D=false; 756 757 //Texture setup 758 PVRTextureHeaderV3 sTextureHeader; 759 PVRTuint8* pTextureData=NULL; 760 761 //Just in case header and pointer for decompression. 762 PVRTextureHeaderV3 sTextureHeaderDecomp; 763 void* pDecompressedData=NULL; 764 765 //Check if it's an old header format 766 if((*(PVRTuint32*)pointer)!=PVRTEX3_IDENT) 767 { 768 //Convert the texture header to the new format. 769 PVRTConvertOldTextureHeaderToV3((PVR_Texture_Header*)pointer,sTextureHeader,pMetaData); 770 771 //Get the texture data. 772 pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+*(PVRTuint32*)pointer; 773 774 bIsLegacyPVR=true; 775 } 776 else 777 { 778 //Get the header from the main pointer. 779 sTextureHeader=*(PVRTextureHeaderV3*)pointer; 780 781 //Get the texture data. 782 pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 783 784 if (pMetaData) 785 { 786 //Read in all the meta data. 787 PVRTuint32 metaDataSize=0; 788 while (metaDataSize<sTextureHeader.u32MetaDataSize) 789 { 790 //Read the DevFourCC and advance the pointer offset. 791 PVRTuint32 DevFourCC=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 792 metaDataSize+=sizeof(DevFourCC); 793 794 //Read the Key and advance the pointer offset. 795 PVRTuint32 u32Key=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 796 metaDataSize+=sizeof(u32Key); 797 798 //Read the DataSize and advance the pointer offset. 799 PVRTuint32 u32DataSize = *(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 800 metaDataSize+=sizeof(u32DataSize); 801 802 //Get the current meta data. 803 MetaDataBlock& currentMetaData = (*pMetaData)[DevFourCC][u32Key]; 804 805 //Assign the values to the meta data. 806 currentMetaData.DevFOURCC=DevFourCC; 807 currentMetaData.u32Key=u32Key; 808 currentMetaData.u32DataSize=u32DataSize; 809 810 //Check for data, if there is any, read it into the meta data. 811 if(u32DataSize > 0) 812 { 813 //Allocate memory. 814 currentMetaData.Data = new PVRTuint8[u32DataSize]; 815 816 //Copy the data. 817 memcpy(currentMetaData.Data, ((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize), u32DataSize); 818 819 //Advance the meta data size. 820 metaDataSize+=u32DataSize; 821 } 822 } 823 } 824 } 825 826 //Return the PVRTextureHeader. 827 if (psTextureHeader) 828 { 829 *(PVRTextureHeaderV3*)psTextureHeader=sTextureHeader; 830 } 831 832 //Setup GL Texture format values. 833 GLenum eTextureFormat = 0; 834 GLenum eTextureInternalFormat = 0; // often this is the same as textureFormat, but not for BGRA8888 on iOS, for instance 835 GLenum eTextureType = 0; 836 837 //Get the OGLES format values. 838 PVRTGetOGLES3TextureFormat(sTextureHeader,eTextureInternalFormat,eTextureFormat,eTextureType); 839 840 bool bIsPVRTCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc"); 841 #ifndef TARGET_OS_IPHONE 842 bool bIsBGRA8888Supported = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_format_BGRA8888"); 843 #else 844 bool bIsBGRA8888Supported = CPVRTgles3Ext::IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888"); 845 #endif 846 #ifndef TARGET_OS_IPHONE 847 bool bIsETCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_OES_compressed_ETC1_RGB8_texture"); 848 #endif 849 850 //Check for compressed formats 851 if (eTextureFormat==0 && eTextureType==0 && eTextureInternalFormat!=0) 852 { 853 if (eTextureInternalFormat>=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG && eTextureInternalFormat<=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG) 854 { 855 //Check for PVRTCI support. 856 if(bIsPVRTCSupported) 857 { 858 bIsCompressedFormatSupported = bIsCompressedFormat = true; 859 } 860 else 861 { 862 //Try to decompress the texture. 863 if(bAllowDecompress) 864 { 865 //Output a warning. 866 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC not supported. Converting to RGBA8888 instead.\n"); 867 868 //Modify boolean values. 869 bIsCompressedFormatSupported = false; 870 bIsCompressedFormat = true; 871 872 //Check if it's 2bpp. 873 bool bIs2bppPVRTC = (eTextureInternalFormat==GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG || eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); 874 875 //Change texture format. 876 eTextureFormat = eTextureInternalFormat = GL_RGBA; 877 eTextureType = GL_UNSIGNED_BYTE; 878 879 //Create a near-identical texture header for the decompressed header. 880 sTextureHeaderDecomp = sTextureHeader; 881 sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; 882 sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; 883 sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); 884 885 //Allocate enough memory for the decompressed data. OGLES2, so only decompress one surface/face. 886 pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); 887 888 //Check the malloc. 889 if (!pDecompressedData) 890 { 891 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); 892 return PVR_FAIL; 893 } 894 895 //Get the dimensions for the current MIP level. 896 PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; 897 PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; 898 899 //Setup temporary variables. 900 PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; 901 PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; 902 903 if (bIsLegacyPVR) 904 { 905 //Decompress all the MIP levels. 906 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 907 { 908 909 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 910 { 911 //Get the face offset. Varies per MIP level. 912 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 913 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 914 915 //Decompress the texture data. 916 PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); 917 918 //Move forward through the pointers. 919 pTempDecompData+=decompressedFaceOffset; 920 pTempCompData+=compressedFaceOffset; 921 922 //Work out the current MIP dimensions. 923 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 924 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 925 } 926 927 //Reset the dims. 928 uiMIPWidth=sTextureHeader.u32Width; 929 uiMIPHeight=sTextureHeader.u32Height; 930 } 931 } 932 else 933 { 934 //Decompress all the MIP levels. 935 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 936 { 937 //Get the face offset. Varies per MIP level. 938 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 939 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 940 941 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 942 { 943 //Decompress the texture data. 944 PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); 945 946 //Move forward through the pointers. 947 pTempDecompData+=decompressedFaceOffset; 948 pTempCompData+=compressedFaceOffset; 949 } 950 951 //Work out the current MIP dimensions. 952 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 953 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 954 } 955 } 956 } 957 else 958 { 959 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC not supported.\n"); 960 return PVR_FAIL; 961 } 962 } 963 } 964 #ifndef TARGET_OS_IPHONE //TODO 965 else if (eTextureInternalFormat==GL_ETC1_RGB8_OES) 966 { 967 if(bIsETCSupported) 968 { 969 bIsCompressedFormatSupported = bIsCompressedFormat = true; 970 } 971 else 972 { 973 if(bAllowDecompress) 974 { 975 //Output a warning. 976 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: ETC not supported. Converting to RGBA8888 instead.\n"); 977 978 //Modify boolean values. 979 bIsCompressedFormatSupported = false; 980 bIsCompressedFormat = true; 981 982 //Change texture format. 983 eTextureFormat = eTextureInternalFormat = GL_RGBA; 984 eTextureType = GL_UNSIGNED_BYTE; 985 986 //Create a near-identical texture header for the decompressed header. 987 sTextureHeaderDecomp = sTextureHeader; 988 sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; 989 sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; 990 sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); 991 992 //Allocate enough memory for the decompressed data. OGLES1, so only decompress one surface/face. 993 pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); 994 995 //Check the malloc. 996 if (!pDecompressedData) 997 { 998 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); 999 return PVR_FAIL; 1000 } 1001 1002 //Get the dimensions for the current MIP level. 1003 PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; 1004 PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; 1005 1006 //Setup temporary variables. 1007 PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; 1008 PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; 1009 1010 if (bIsLegacyPVR) 1011 { 1012 //Decompress all the MIP levels. 1013 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 1014 { 1015 1016 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 1017 { 1018 //Get the face offset. Varies per MIP level. 1019 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 1020 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 1021 1022 //Decompress the texture data. 1023 PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); 1024 1025 //Move forward through the pointers. 1026 pTempDecompData+=decompressedFaceOffset; 1027 pTempCompData+=compressedFaceOffset; 1028 1029 //Work out the current MIP dimensions. 1030 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 1031 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 1032 } 1033 1034 //Reset the dims. 1035 uiMIPWidth=sTextureHeader.u32Width; 1036 uiMIPHeight=sTextureHeader.u32Height; 1037 } 1038 } 1039 else 1040 { 1041 //Decompress all the MIP levels. 1042 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 1043 { 1044 //Get the face offset. Varies per MIP level. 1045 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 1046 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 1047 1048 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 1049 { 1050 //Decompress the texture data. 1051 PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); 1052 1053 //Move forward through the pointers. 1054 pTempDecompData+=decompressedFaceOffset; 1055 pTempCompData+=compressedFaceOffset; 1056 } 1057 1058 //Work out the current MIP dimensions. 1059 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 1060 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 1061 } 1062 } 1063 } 1064 else 1065 { 1066 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: ETC not supported.\n"); 1067 return PVR_FAIL; 1068 } 1069 } 1070 } 1071 #endif 1072 } 1073 1074 //Check for BGRA support. 1075 if(eTextureFormat==GL_BGRA_IMG) 1076 { 1077 #ifdef TARGET_OS_IPHONE 1078 eTextureInternalFormat = GL_RGBA; 1079 #endif 1080 if(!bIsBGRA8888Supported) 1081 { 1082 #ifdef TARGET_OS_IPHONE 1083 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_APPLE_texture_format_BGRA8888 is unsupported.\n"); 1084 #else 1085 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_IMG_texture_format_BGRA8888 is unsupported.\n"); 1086 #endif 1087 return PVR_FAIL; 1088 } 1089 } 1090 1091 //Deal with unsupported texture formats 1092 if (eTextureInternalFormat==0) 1093 { 1094 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type not supported.\n"); 1095 return PVR_FAIL; 1096 } 1097 1098 //PVR files are never row aligned. 1099 glPixelStorei(GL_UNPACK_ALIGNMENT,1); 1100 1101 //Generate a texture 1102 glGenTextures(1, texName); 1103 1104 //Initialise a texture target. 1105 GLint eTarget=GL_TEXTURE_2D; 1106 1107 //A mix of arrays/cubes/depths are not permitted in OpenGL ES. Check. 1108 if (sTextureHeader.u32NumFaces>1 || sTextureHeader.u32NumSurfaces>1 || sTextureHeader.u32Depth>1) 1109 { 1110 if((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32NumSurfaces>1)) 1111 { 1112 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of cubemaps are not supported by OpenGL ES 3.0\n"); 1113 return PVR_FAIL; 1114 } 1115 else if ((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32Depth>1)) 1116 { 1117 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: 3D Cubemap textures are not supported by OpenGL ES 3.0\n"); 1118 return PVR_FAIL; 1119 } 1120 else if ((sTextureHeader.u32NumSurfaces>1) && (sTextureHeader.u32Depth>1)) 1121 { 1122 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of 3D textures are not supported by OpenGL ES 3.0\n"); 1123 return PVR_FAIL; 1124 } 1125 1126 if(sTextureHeader.u32NumSurfaces>1) 1127 { 1128 eTarget=GL_TEXTURE_2D_ARRAY; 1129 bUsesTexImage3D=true; 1130 } 1131 else if(sTextureHeader.u32NumFaces>1) 1132 { 1133 eTarget=GL_TEXTURE_CUBE_MAP; 1134 } 1135 else if (sTextureHeader.u32Depth>1) 1136 { 1137 eTarget=GL_TEXTURE_3D; 1138 bUsesTexImage3D=true; 1139 } 1140 } 1141 1142 //Bind the texture 1143 glBindTexture(eTarget, *texName); 1144 1145 if(glGetError()) 1146 { 1147 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glBindTexture() failed.\n"); 1148 return PVR_FAIL; 1149 } 1150 1151 //Temporary data to save on if statements within the load loops. 1152 PVRTuint8* pTempData=NULL; 1153 PVRTextureHeaderV3 *psTempHeader=NULL; 1154 if (bIsCompressedFormat && !bIsCompressedFormatSupported) 1155 { 1156 pTempData=(PVRTuint8*)pDecompressedData; 1157 psTempHeader=&sTextureHeaderDecomp; 1158 } 1159 else 1160 { 1161 pTempData=pTextureData; 1162 psTempHeader=&sTextureHeader; 1163 } 1164 1165 //Initialise the current MIP size. 1166 PVRTuint32 uiCurrentMIPSize=0; 1167 1168 //Initialise the width/height 1169 PVRTuint32 u32MIPWidth = sTextureHeader.u32Width; 1170 PVRTuint32 u32MIPHeight = sTextureHeader.u32Height; 1171 PVRTuint32 u32MIPDepth; 1172 if (psTempHeader->u32Depth>1) 1173 { 1174 u32MIPDepth=psTempHeader->u32Depth; //3d texture. 1175 } 1176 else 1177 { 1178 u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays. 1179 } 1180 1181 //Loop through all MIP levels. 1182 if (bIsLegacyPVR) 1183 { 1184 //Temporary texture target. 1185 GLint eTextureTarget=eTarget; 1186 1187 //Cubemaps are special. 1188 if (eTextureTarget==GL_TEXTURE_CUBE_MAP) 1189 { 1190 eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X; 1191 } 1192 1193 //Loop through all the faces. 1194 for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) 1195 { 1196 //Loop through all the mip levels. 1197 for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) 1198 { 1199 //Get the current MIP size. 1200 uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); 1201 1202 if (uiMIPLevel>=nLoadFromLevel) 1203 { 1204 //Upload the texture 1205 if (bUsesTexImage3D) 1206 { 1207 if (bIsCompressedFormat && bIsCompressedFormatSupported) 1208 { 1209 glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); 1210 } 1211 else 1212 { 1213 glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData); 1214 } 1215 } 1216 else 1217 { 1218 if (bIsCompressedFormat && bIsCompressedFormatSupported) 1219 { 1220 glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); 1221 } 1222 else 1223 { 1224 glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); 1225 } 1226 } 1227 } 1228 pTempData+=uiCurrentMIPSize; 1229 1230 //Reduce the MIP Size. 1231 u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); 1232 u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); 1233 if (psTempHeader->u32Depth>1) 1234 { 1235 u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1); 1236 } 1237 } 1238 1239 //Increase the texture target. 1240 eTextureTarget++; 1241 1242 //Reset the current MIP dimensions. 1243 u32MIPWidth=psTempHeader->u32Width; 1244 u32MIPHeight=psTempHeader->u32Height; 1245 1246 if (psTempHeader->u32Depth>1) 1247 { 1248 u32MIPDepth=psTempHeader->u32Depth; 1249 } 1250 else 1251 { 1252 u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays. 1253 } 1254 1255 //Error check 1256 if(glGetError()) 1257 { 1258 FREE(pDecompressedData); 1259 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 1260 return PVR_FAIL; 1261 } 1262 } 1263 } 1264 else 1265 { 1266 for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) 1267 { 1268 //Get the current MIP size. 1269 uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); 1270 1271 GLint eTextureTarget=eTarget; 1272 //Cubemaps are special. 1273 if (eTextureTarget==GL_TEXTURE_CUBE_MAP) 1274 { 1275 eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X; 1276 } 1277 1278 for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) 1279 { 1280 if (uiMIPLevel>=nLoadFromLevel) 1281 { 1282 //Upload the texture 1283 if (bUsesTexImage3D) 1284 { 1285 //Upload the texture 1286 if (bIsCompressedFormat && bIsCompressedFormatSupported) 1287 { 1288 glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); 1289 } 1290 else 1291 { 1292 glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData); 1293 } 1294 } 1295 else 1296 { 1297 //Upload the texture 1298 if (bIsCompressedFormat && bIsCompressedFormatSupported) 1299 { 1300 glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); 1301 } 1302 else 1303 { 1304 glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); 1305 } 1306 } 1307 } 1308 pTempData+=uiCurrentMIPSize; 1309 eTextureTarget++; 1310 } 1311 1312 //Reduce the MIP Size. 1313 u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); 1314 u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); 1315 if (psTempHeader->u32Depth>1) 1316 { 1317 u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1); //Only reduce depth for 3D textures, not texture arrays. 1318 } 1319 1320 //Error check 1321 if(glGetError()) 1322 { 1323 FREE(pDecompressedData); 1324 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 1325 return PVR_FAIL; 1326 } 1327 } 1328 } 1329 1330 FREE(pDecompressedData); 1331 1332 //Error check 1333 if(glGetError()) 1334 { 1335 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 1336 return PVR_FAIL; 1337 } 1338 1339 //Set Minification and Magnification filters according to whether MIP maps are present. 1340 if(eTextureType==GL_FLOAT || eTextureType==GL_HALF_FLOAT) 1341 { 1342 if(sTextureHeader.u32MIPMapCount==1) 1343 { // Texture filter modes are limited to these for float textures 1344 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1345 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1346 } 1347 else 1348 { 1349 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 1350 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1351 } 1352 } 1353 else 1354 { 1355 if(sTextureHeader.u32MIPMapCount==1) 1356 { 1357 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1358 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1359 } 1360 else 1361 { 1362 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 1363 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1364 } 1365 } 1366 1367 if( (sTextureHeader.u32Width & (sTextureHeader.u32Width - 1)) | (sTextureHeader.u32Height & (sTextureHeader.u32Height - 1))) 1368 { 1369 /* 1370 NPOT textures requires the wrap mode to be set explicitly to 1371 GL_CLAMP_TO_EDGE or the texture will be inconsistent. 1372 */ 1373 glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1374 glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1375 } 1376 else 1377 { 1378 glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); 1379 glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); 1380 } 1381 1382 //Error check 1383 if(glGetError()) 1384 { 1385 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexParameter() failed.\n"); 1386 return PVR_FAIL; 1387 } 1388 1389 return PVR_SUCCESS; 1390 } 1391 1392 /*!*************************************************************************** 1393 @Function PVRTTextureLoadFromPVR 1394 @Input filename Filename of the .PVR file to load the texture from 1395 @Modified texName the OpenGL ES texture name as returned by glBindTexture 1396 @Modified psTextureHeader Pointer to a PVR_Texture_Header struct. Modified to 1397 contain the header data of the returned texture Ignored if NULL. 1398 @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware. 1399 @Input nLoadFromLevel Which mipmap level to start loading from (0=all) 1400 @Modified pMetaData If a valid map is supplied, this will return any and all 1401 MetaDataBlocks stored in the texture, organised by DevFourCC 1402 then identifier. Supplying NULL will ignore all MetaData. 1403 @Return PVR_SUCCESS on success 1404 @Description Allows textures to be stored in binary PVR files and loaded in. Can load parts of a 1405 mipmaped texture (ie skipping the highest detailed levels). 1406 Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR 1407 if mipmaps are present, GL_LINEAR/GL_LINEAR otherwise. 1408 *****************************************************************************/ 1409 EPVRTError PVRTTextureLoadFromPVR( const char * const filename, 1410 GLuint * const texName, 1411 const void *psTextureHeader, 1412 bool bAllowDecompress, 1413 const unsigned int nLoadFromLevel, 1414 CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData) 1415 { 1416 //Attempt to open file. 1417 CPVRTResourceFile TexFile(filename); 1418 1419 //Check file opened successfully. 1420 if (!TexFile.IsOpen()) 1421 { 1422 return PVR_FAIL; 1423 } 1424 1425 //Header size. 1426 PVRTuint32 u32HeaderSize=0; 1427 1428 //Boolean whether to byte swap the texture data or not. 1429 bool bSwapDataEndianness=false; 1430 1431 //Texture header to check against. 1432 PVRTextureHeaderV3 sTextureHeader; 1433 1434 //The channel type for endian swapping. 1435 EPVRTVariableType u32CurrentChannelType=ePVRTVarTypeUnsignedByte; 1436 1437 //Check the first word of the file and see if it's equal to the current identifier (or reverse identifier) 1438 if(*(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT && *(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT_REV) 1439 { 1440 //Swap the header bytes if necessary. 1441 if(!PVRTIsLittleEndian()) 1442 { 1443 bSwapDataEndianness=true; 1444 PVRTuint32 u32HeaderSize=PVRTByteSwap32(*(PVRTuint32*)TexFile.DataPtr()); 1445 1446 for (PVRTuint32 i=0; i<u32HeaderSize; ++i) 1447 { 1448 PVRTByteSwap( (PVRTuint8*)( ( (PVRTuint32*)TexFile.DataPtr() )+i),sizeof(PVRTuint32) ); 1449 } 1450 } 1451 1452 //Get a pointer to the header. 1453 PVR_Texture_Header* sLegacyTextureHeader=(PVR_Texture_Header*)TexFile.DataPtr(); 1454 1455 //Set the header size. 1456 u32HeaderSize=sLegacyTextureHeader->dwHeaderSize; 1457 1458 //We only really need the channel type. 1459 PVRTuint64 tempFormat; 1460 EPVRTColourSpace tempColourSpace; 1461 bool tempIsPreMult; 1462 1463 //Map the enum to get the channel type. 1464 PVRTMapLegacyTextureEnumToNewFormat( (PVRTPixelType)( sLegacyTextureHeader->dwpfFlags&0xff),tempFormat,tempColourSpace, u32CurrentChannelType, tempIsPreMult); 1465 } 1466 // If the header file has a reverse identifier, then we need to swap endianness 1467 else if(*(PVRTuint32*)TexFile.DataPtr()==PVRTEX_CURR_IDENT_REV) 1468 { 1469 //Setup the texture header 1470 sTextureHeader=*(PVRTextureHeaderV3*)TexFile.DataPtr(); 1471 1472 bSwapDataEndianness=true; 1473 PVRTextureHeaderV3* pTextureHeader=(PVRTextureHeaderV3*)TexFile.DataPtr(); 1474 1475 pTextureHeader->u32ChannelType=PVRTByteSwap32(pTextureHeader->u32ChannelType); 1476 pTextureHeader->u32ColourSpace=PVRTByteSwap32(pTextureHeader->u32ColourSpace); 1477 pTextureHeader->u32Depth=PVRTByteSwap32(pTextureHeader->u32Depth); 1478 pTextureHeader->u32Flags=PVRTByteSwap32(pTextureHeader->u32Flags); 1479 pTextureHeader->u32Height=PVRTByteSwap32(pTextureHeader->u32Height); 1480 pTextureHeader->u32MetaDataSize=PVRTByteSwap32(pTextureHeader->u32MetaDataSize); 1481 pTextureHeader->u32MIPMapCount=PVRTByteSwap32(pTextureHeader->u32MIPMapCount); 1482 pTextureHeader->u32NumFaces=PVRTByteSwap32(pTextureHeader->u32NumFaces); 1483 pTextureHeader->u32NumSurfaces=PVRTByteSwap32(pTextureHeader->u32NumSurfaces); 1484 pTextureHeader->u32Version=PVRTByteSwap32(pTextureHeader->u32Version); 1485 pTextureHeader->u32Width=PVRTByteSwap32(pTextureHeader->u32Width); 1486 PVRTByteSwap((PVRTuint8*)&pTextureHeader->u64PixelFormat,sizeof(PVRTuint64)); 1487 1488 //Channel type. 1489 u32CurrentChannelType=(EPVRTVariableType)pTextureHeader->u32ChannelType; 1490 1491 //Header size. 1492 u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 1493 } 1494 else 1495 { 1496 //Header size. 1497 u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 1498 } 1499 1500 // Convert the data if needed 1501 if(bSwapDataEndianness) 1502 { 1503 //Get the size of the variables types. 1504 PVRTuint32 ui32VariableSize=0; 1505 switch(u32CurrentChannelType) 1506 { 1507 case ePVRTVarTypeFloat: 1508 case ePVRTVarTypeUnsignedInteger: 1509 case ePVRTVarTypeUnsignedIntegerNorm: 1510 case ePVRTVarTypeSignedInteger: 1511 case ePVRTVarTypeSignedIntegerNorm: 1512 { 1513 ui32VariableSize=4; 1514 break; 1515 } 1516 case ePVRTVarTypeUnsignedShort: 1517 case ePVRTVarTypeUnsignedShortNorm: 1518 case ePVRTVarTypeSignedShort: 1519 case ePVRTVarTypeSignedShortNorm: 1520 { 1521 ui32VariableSize=2; 1522 break; 1523 } 1524 case ePVRTVarTypeUnsignedByte: 1525 case ePVRTVarTypeUnsignedByteNorm: 1526 case ePVRTVarTypeSignedByte: 1527 case ePVRTVarTypeSignedByteNorm: 1528 { 1529 ui32VariableSize=1; 1530 break; 1531 } 1532 default: 1533 return PVR_FAIL; 1534 } 1535 1536 //If the size of the variable type is greater than 1, then we need to byte swap. 1537 if (ui32VariableSize>1) 1538 { 1539 //Get the texture data. 1540 PVRTuint8* pu8OrigData = ( (PVRTuint8*)TexFile.DataPtr() + u32HeaderSize); 1541 1542 //Get the size of the texture data. 1543 PVRTuint32 ui32TextureDataSize = PVRTGetTextureDataSize(sTextureHeader); 1544 1545 //Loop through and byte swap all the data. It's swapped in place so no need to do anything special. 1546 for(PVRTuint32 i = 0; i < ui32TextureDataSize; i+=ui32VariableSize) 1547 { 1548 PVRTByteSwap(pu8OrigData+i,ui32VariableSize); 1549 } 1550 } 1551 } 1552 1553 return PVRTTextureLoadFromPointer(TexFile.DataPtr(), texName, psTextureHeader, bAllowDecompress, nLoadFromLevel,NULL,pMetaData); 1554 } 1555 1556 /***************************************************************************** 1557 End of file (PVRTTextureAPI.cpp) 1558 *****************************************************************************/ 1559 1560