1/****************************************************************************** 2 3 @File OGLES2/PVRTTextureAPI.cpp 4 5 @Title OGLES2/PVRTTextureAPI 6 7 @Version 8 9 @Copyright Copyright (c) Imagination Technologies Limited. 10 11 @Platform ANSI compatible 12 13 @Description OGLES2 texture loading. 14 15******************************************************************************/ 16 17#include <string.h> 18#include <stdlib.h> 19 20#include "PVRTContext.h" 21#include "PVRTgles2Ext.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/*!*********************************************************************** 37 @Function: PVRTGetOGLESTextureFormat 38 @Input: sTextureHeader 39 @Modified: internalformat 40 @Modified: format 41 @Modified: type 42 @Description: Gets the OpenGLES equivalent values of internal format, 43 format and type for this texture header. This will return 44 any supported OpenGLES texture values, it is up to the user 45 to decide if these are valid for their current platform. 46*************************************************************************/ 47static const void PVRTGetOGLES2TextureFormat(const PVRTextureHeaderV3& sTextureHeader, PVRTuint32& internalformat, PVRTuint32& format, PVRTuint32& type) 48{ 49 PVRTuint64 PixelFormat = sTextureHeader.u64PixelFormat; 50 EPVRTVariableType ChannelType = (EPVRTVariableType)sTextureHeader.u32ChannelType; 51 52 //Initialisation. Any invalid formats will return 0 always. 53 format = 0; 54 type = 0; 55 internalformat=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 internalformat=GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 69 return; 70 } 71 case ePVRTPF_PVRTCI_2bpp_RGBA: 72 { 73 internalformat=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 74 return; 75 } 76 case ePVRTPF_PVRTCI_4bpp_RGB: 77 { 78 internalformat=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 79 return; 80 } 81 case ePVRTPF_PVRTCI_4bpp_RGBA: 82 { 83 internalformat=GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 84 return; 85 } 86#ifndef TARGET_OS_IPHONE 87 case ePVRTPF_PVRTCII_2bpp: 88 { 89 internalformat=GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG; 90 return; 91 } 92 case ePVRTPF_PVRTCII_4bpp: 93 { 94 internalformat=GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG; 95 return; 96 } 97 case ePVRTPF_ETC1: 98 { 99 internalformat=GL_ETC1_RGB8_OES; 100 return; 101 } 102#endif 103 default: 104 return; 105 } 106 } 107 else 108 { 109 switch (ChannelType) 110 { 111 case ePVRTVarTypeFloat: 112 { 113 switch (PixelFormat) 114 { 115 //HALF_FLOAT_OES 116 case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): 117 { 118 type=GL_HALF_FLOAT_OES; 119 format = GL_RGBA; 120 internalformat=GL_RGBA; 121 return; 122 } 123 case PVRTGENPIXELID3('r','g','b',16,16,16): 124 { 125 type=GL_HALF_FLOAT_OES; 126 format = GL_RGB; 127 internalformat=GL_RGB; 128 return; 129 } 130 case PVRTGENPIXELID2('l','a',16,16): 131 { 132 type=GL_HALF_FLOAT_OES; 133 format = GL_LUMINANCE_ALPHA; 134 internalformat=GL_LUMINANCE_ALPHA; 135 return; 136 } 137 case PVRTGENPIXELID1('l',16): 138 { 139 type=GL_HALF_FLOAT_OES; 140 format = GL_LUMINANCE; 141 internalformat=GL_LUMINANCE; 142 return; 143 } 144 case PVRTGENPIXELID1('a',16): 145 { 146 type=GL_HALF_FLOAT_OES; 147 format = GL_ALPHA; 148 internalformat=GL_ALPHA; 149 return; 150 } 151 //FLOAT (OES) 152 case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): 153 { 154 type=GL_FLOAT; 155 format = GL_RGBA; 156 internalformat=GL_RGBA; 157 return; 158 } 159 case PVRTGENPIXELID3('r','g','b',32,32,32): 160 { 161 type=GL_FLOAT; 162 format = GL_RGB; 163 internalformat=GL_RGB; 164 return; 165 } 166 case PVRTGENPIXELID2('l','a',32,32): 167 { 168 type=GL_FLOAT; 169 format = GL_LUMINANCE_ALPHA; 170 internalformat=GL_LUMINANCE_ALPHA; 171 return; 172 } 173 case PVRTGENPIXELID1('l',32): 174 { 175 type=GL_FLOAT; 176 format = GL_LUMINANCE; 177 internalformat=GL_LUMINANCE; 178 return; 179 } 180 case PVRTGENPIXELID1('a',32): 181 { 182 type=GL_FLOAT; 183 format = GL_ALPHA; 184 internalformat=GL_ALPHA; 185 return; 186 } 187 } 188 break; 189 } 190 case ePVRTVarTypeUnsignedByteNorm: 191 { 192 type = GL_UNSIGNED_BYTE; 193 switch (PixelFormat) 194 { 195 case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): 196 { 197 format = internalformat = GL_RGBA; 198 return; 199 } 200 case PVRTGENPIXELID3('r','g','b',8,8,8): 201 { 202 format = internalformat = GL_RGB; 203 return; 204 } 205 case PVRTGENPIXELID2('l','a',8,8): 206 { 207 format = internalformat = GL_LUMINANCE_ALPHA; 208 return; 209 } 210 case PVRTGENPIXELID1('l',8): 211 { 212 format = internalformat = GL_LUMINANCE; 213 return; 214 } 215 case PVRTGENPIXELID1('a',8): 216 { 217 format = internalformat = GL_ALPHA; 218 return; 219 } 220 case PVRTGENPIXELID4('b','g','r','a',8,8,8,8): 221 { 222 format = internalformat = GL_BGRA; 223 return; 224 } 225 } 226 break; 227 } 228 case ePVRTVarTypeUnsignedShortNorm: 229 { 230 switch (PixelFormat) 231 { 232 case PVRTGENPIXELID4('r','g','b','a',4,4,4,4): 233 { 234 type = GL_UNSIGNED_SHORT_4_4_4_4; 235 format = internalformat = GL_RGBA; 236 return; 237 } 238 case PVRTGENPIXELID4('r','g','b','a',5,5,5,1): 239 { 240 type = GL_UNSIGNED_SHORT_5_5_5_1; 241 format = internalformat = GL_RGBA; 242 return; 243 } 244 case PVRTGENPIXELID3('r','g','b',5,6,5): 245 { 246 type = GL_UNSIGNED_SHORT_5_6_5; 247 format = internalformat = GL_RGB; 248 return; 249 } 250 } 251 break; 252 } 253 default: 254 return; 255 } 256 } 257} 258 259/*!*************************************************************************** 260@Function PVRTTextureTile 261@Modified pOut The tiled texture in system memory 262@Input pIn The source texture 263@Input nRepeatCnt Number of times to repeat the source texture 264@Description Allocates and fills, in system memory, a texture large enough 265 to repeat the source texture specified number of times. 266*****************************************************************************/ 267void PVRTTextureTile( 268 PVRTextureHeaderV3 **pOut, 269 const PVRTextureHeaderV3 * const pIn, 270 const int nRepeatCnt) 271{ 272 unsigned int nFormat = 0, nType = 0, nBPP, nSize, nElW = 0, nElH = 0, nElD = 0; 273 PVRTuint8 *pMmSrc, *pMmDst; 274 unsigned int nLevel; 275 PVRTextureHeaderV3 *psTexHeaderNew; 276 277 _ASSERT(pIn->u32Width); 278 _ASSERT(pIn->u32Width == pIn->u32Height); 279 _ASSERT(nRepeatCnt > 1); 280 281 PVRTGetOGLES2TextureFormat(*pIn,nFormat,nFormat,nType); 282 PVRTGetFormatMinDims(pIn->u64PixelFormat,nElW,nElH,nElD); 283 284 nBPP = PVRTGetBitsPerPixel(pIn->u64PixelFormat); 285 nSize = pIn->u32Width * nRepeatCnt; 286 287 psTexHeaderNew = PVRTTextureCreate(nSize, nSize, nElW, nElH, nBPP, true); 288 *psTexHeaderNew = *pIn; 289 pMmDst = (PVRTuint8*)psTexHeaderNew + sizeof(*psTexHeaderNew); 290 pMmSrc = (PVRTuint8*)pIn + sizeof(*pIn); 291 292 for(nLevel = 0; ((unsigned int)1 << nLevel) < nSize; ++nLevel) 293 { 294 int nBlocksDstW = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElW); 295 int nBlocksDstH = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElH); 296 int nBlocksSrcW = PVRT_MAX((unsigned int)1, (pIn->u32Width >> nLevel) / nElW); 297 int nBlocksSrcH = PVRT_MAX((unsigned int)1, (pIn->u32Height >> nLevel) / nElH); 298 int nBlocksS = nBPP * nElW * nElH / 8; 299 300 PVRTTextureLoadTiled( 301 pMmDst, 302 nBlocksDstW, 303 nBlocksDstH, 304 pMmSrc, 305 nBlocksSrcW, 306 nBlocksSrcH, 307 nBlocksS, 308 (/*pIn->u64PixelFormat>=ePVRTPF_PVRTCI_2bpp_RGB &&*/ pIn->u64PixelFormat<=ePVRTPF_PVRTCI_4bpp_RGBA) ? true : false); 309 310 pMmDst += nBlocksDstW * nBlocksDstH * nBlocksS; 311 pMmSrc += nBlocksSrcW * nBlocksSrcH * nBlocksS; 312 } 313 314 psTexHeaderNew->u32Width = nSize; 315 psTexHeaderNew->u32Height = nSize; 316 psTexHeaderNew->u32MIPMapCount = nLevel+1; 317 *pOut = psTexHeaderNew; 318} 319 320/*!*************************************************************************** 321 @Function PVRTTextureLoadFromPointer 322 @Input pointer Pointer to header-texture's structure 323 @Modified texName the OpenGL ES texture name as returned by glBindTexture 324 @Modified psTextureHeader Pointer to a PVRTextureHeaderV3 struct. Modified to 325 contain the header data of the returned texture Ignored if NULL. 326 @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware. 327 @Input nLoadFromLevel Which mip map level to start loading from (0=all) 328 @Input texPtr If null, texture follows header, else texture is here. 329 @Modified pMetaData If a valid map is supplied, this will return any and all 330 MetaDataBlocks stored in the texture, organised by DevFourCC 331 then identifier. Supplying NULL will ignore all MetaData. 332 @Return PVR_SUCCESS on success 333 @Description Allows textures to be stored in C header files and loaded in. Can load parts of a 334 mip mapped texture (i.e. skipping the highest detailed levels). In OpenGL Cube Map, each 335 texture's up direction is defined as next (view direction, up direction), 336 (+x,-y)(-x,-y)(+y,+z)(-y,-z)(+z,-y)(-z,-y). 337 Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR 338 if mip maps are present, GL_LINEAR/GL_LINEAR otherwise. 339*****************************************************************************/ 340EPVRTError PVRTTextureLoadFromPointer( const void* pointer, 341 GLuint *const texName, 342 const void *psTextureHeader, 343 bool bAllowDecompress, 344 const unsigned int nLoadFromLevel, 345 const void * const texPtr, 346 CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData) 347{ 348 //Compression bools 349 bool bIsCompressedFormatSupported=false; 350 bool bIsCompressedFormat=false; 351 bool bIsLegacyPVR=false; 352 bool bUsesTexImage3D = false; 353 354 CPVRTgles2Ext extensions; 355 extensions.LoadExtensions(); 356 357 //Texture setup 358 PVRTextureHeaderV3 sTextureHeader; 359 PVRTuint8* pTextureData=NULL; 360 361 //Just in case header and pointer for decompression. 362 PVRTextureHeaderV3 sTextureHeaderDecomp; 363 void* pDecompressedData=NULL; 364 365 //Check if it's an old header format 366 if((*(PVRTuint32*)pointer)!=PVRTEX3_IDENT) 367 { 368 //Convert the texture header to the new format. 369 PVRTConvertOldTextureHeaderToV3((PVR_Texture_Header*)pointer,sTextureHeader,pMetaData); 370 371 //Get the texture data. 372 pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+*(PVRTuint32*)pointer; 373 374 bIsLegacyPVR=true; 375 } 376 else 377 { 378 //Get the header from the main pointer. 379 sTextureHeader=*(PVRTextureHeaderV3*)pointer; 380 381 //Get the texture data. 382 pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 383 384 if (pMetaData) 385 { 386 //Read in all the meta data. 387 PVRTuint32 metaDataSize=0; 388 while (metaDataSize<sTextureHeader.u32MetaDataSize) 389 { 390 //Read the DevFourCC and advance the pointer offset. 391 PVRTuint32 DevFourCC=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 392 metaDataSize+=sizeof(DevFourCC); 393 394 //Read the Key and advance the pointer offset. 395 PVRTuint32 u32Key=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 396 metaDataSize+=sizeof(u32Key); 397 398 //Read the DataSize and advance the pointer offset. 399 PVRTuint32 u32DataSize = *(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); 400 metaDataSize+=sizeof(u32DataSize); 401 402 //Get the current meta data. 403 MetaDataBlock& currentMetaData = (*pMetaData)[DevFourCC][u32Key]; 404 405 //Assign the values to the meta data. 406 currentMetaData.DevFOURCC=DevFourCC; 407 currentMetaData.u32Key=u32Key; 408 currentMetaData.u32DataSize=u32DataSize; 409 410 //Check for data, if there is any, read it into the meta data. 411 if(u32DataSize > 0) 412 { 413 //Allocate memory. 414 currentMetaData.Data = new PVRTuint8[u32DataSize]; 415 416 //Copy the data. 417 memcpy(currentMetaData.Data, ((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize), u32DataSize); 418 419 //Advance the meta data size. 420 metaDataSize+=u32DataSize; 421 } 422 } 423 } 424 } 425 426 //Return the PVRTextureHeader. 427 if (psTextureHeader) 428 { 429 *(PVRTextureHeaderV3*)psTextureHeader=sTextureHeader; 430 } 431 432 //Setup GL Texture format values. 433 GLenum eTextureFormat = 0; 434 GLenum eTextureInternalFormat = 0; // often this is the same as textureFormat, but not for BGRA8888 on iOS, for instance 435 GLenum eTextureType = 0; 436 437 //Get the OGLES format values. 438 PVRTGetOGLES2TextureFormat(sTextureHeader,eTextureInternalFormat,eTextureFormat,eTextureType); 439 440 //Check supported texture formats. 441 bool bIsPVRTCSupported = CPVRTgles2Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc"); 442 bool bIsPVRTC2Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc2"); 443#ifndef TARGET_OS_IPHONE 444 bool bIsBGRA8888Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_IMG_texture_format_BGRA8888"); 445#else 446 bool bIsBGRA8888Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888"); 447#endif 448 bool bIsFloat16Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_texture_half_float"); 449 bool bIsFloat32Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_texture_float"); 450 bool bIsTexture3DSupported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_texture_3D"); 451#ifndef TARGET_OS_IPHONE 452 bool bIsETCSupported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_compressed_ETC1_RGB8_texture"); 453#endif 454 455 //Check for compressed formats 456 if (eTextureFormat==0 && eTextureType==0 && eTextureInternalFormat!=0) 457 { 458 if (eTextureInternalFormat>=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG && eTextureInternalFormat<=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG) 459 { 460 //Check for PVRTCI support. 461 if(bIsPVRTCSupported) 462 { 463 bIsCompressedFormatSupported = bIsCompressedFormat = true; 464 } 465 else 466 { 467 //Try to decompress the texture. 468 if(bAllowDecompress) 469 { 470 //Output a warning. 471 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC not supported. Converting to RGBA8888 instead.\n"); 472 473 //Modify boolean values. 474 bIsCompressedFormatSupported = false; 475 bIsCompressedFormat = true; 476 477 //Check if it's 2bpp. 478 bool bIs2bppPVRTC = (eTextureInternalFormat==GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG || eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); 479 480 //Change texture format. 481 eTextureFormat = eTextureInternalFormat = GL_RGBA; 482 eTextureType = GL_UNSIGNED_BYTE; 483 484 //Create a near-identical texture header for the decompressed header. 485 sTextureHeaderDecomp = sTextureHeader; 486 sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; 487 sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; 488 sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); 489 490 //Allocate enough memory for the decompressed data. OGLES2, so only decompress one surface, but all faces. 491 pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); 492 493 //Check the malloc. 494 if (!pDecompressedData) 495 { 496 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); 497 return PVR_FAIL; 498 } 499 500 //Get the dimensions for the current MIP level. 501 PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; 502 PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; 503 504 //Setup temporary variables. 505 PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; 506 PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; 507 508 if (bIsLegacyPVR) 509 { 510 //Decompress all the MIP levels. 511 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 512 { 513 514 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 515 { 516 //Get the face offset. Varies per MIP level. 517 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 518 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 519 520 //Decompress the texture data. 521 PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); 522 523 //Move forward through the pointers. 524 pTempDecompData+=decompressedFaceOffset; 525 pTempCompData+=compressedFaceOffset; 526 527 //Work out the current MIP dimensions. 528 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 529 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 530 } 531 532 //Reset the dims. 533 uiMIPWidth=sTextureHeader.u32Width; 534 uiMIPHeight=sTextureHeader.u32Height; 535 } 536 } 537 else 538 { 539 //Decompress all the MIP levels. 540 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 541 { 542 //Get the face offset. Varies per MIP level. 543 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 544 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 545 546 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 547 { 548 //Decompress the texture data. 549 PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); 550 551 //Move forward through the pointers. 552 pTempDecompData+=decompressedFaceOffset; 553 pTempCompData+=compressedFaceOffset; 554 } 555 556 //Work out the current MIP dimensions. 557 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 558 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 559 } 560 } 561 } 562 else 563 { 564 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC not supported.\n"); 565 return PVR_FAIL; 566 } 567 } 568 } 569#ifndef TARGET_OS_IPHONE //TODO 570 else if (eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG || eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG) 571 { 572 //Check for PVRTCI support. 573 if(bIsPVRTC2Supported) 574 { 575 bIsCompressedFormatSupported = bIsCompressedFormat = true; 576 } 577 else 578 { 579 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC not supported.\n"); 580 return PVR_FAIL; 581 } 582 } 583 else if (eTextureInternalFormat==GL_ETC1_RGB8_OES) 584 { 585 if(bIsETCSupported) 586 { 587 bIsCompressedFormatSupported = bIsCompressedFormat = true; 588 } 589 else 590 { 591 if(bAllowDecompress) 592 { 593 //Output a warning. 594 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: ETC not supported. Converting to RGBA8888 instead.\n"); 595 596 //Modify boolean values. 597 bIsCompressedFormatSupported = false; 598 bIsCompressedFormat = true; 599 600 //Change texture format. 601 eTextureFormat = eTextureInternalFormat = GL_RGBA; 602 eTextureType = GL_UNSIGNED_BYTE; 603 604 //Create a near-identical texture header for the decompressed header. 605 sTextureHeaderDecomp = sTextureHeader; 606 sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; 607 sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; 608 sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); 609 610 //Allocate enough memory for the decompressed data. OGLES1, so only decompress one surface/face. 611 pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); 612 613 //Check the malloc. 614 if (!pDecompressedData) 615 { 616 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); 617 return PVR_FAIL; 618 } 619 620 //Get the dimensions for the current MIP level. 621 PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; 622 PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; 623 624 //Setup temporary variables. 625 PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; 626 PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; 627 628 if (bIsLegacyPVR) 629 { 630 //Decompress all the MIP levels. 631 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 632 { 633 634 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 635 { 636 //Get the face offset. Varies per MIP level. 637 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 638 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 639 640 //Decompress the texture data. 641 PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); 642 643 //Move forward through the pointers. 644 pTempDecompData+=decompressedFaceOffset; 645 pTempCompData+=compressedFaceOffset; 646 647 //Work out the current MIP dimensions. 648 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 649 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 650 } 651 652 //Reset the dims. 653 uiMIPWidth=sTextureHeader.u32Width; 654 uiMIPHeight=sTextureHeader.u32Height; 655 } 656 } 657 else 658 { 659 //Decompress all the MIP levels. 660 for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) 661 { 662 //Get the face offset. Varies per MIP level. 663 PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); 664 PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); 665 666 for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) 667 { 668 //Decompress the texture data. 669 PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); 670 671 //Move forward through the pointers. 672 pTempDecompData+=decompressedFaceOffset; 673 pTempCompData+=compressedFaceOffset; 674 } 675 676 //Work out the current MIP dimensions. 677 uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); 678 uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); 679 } 680 } 681 } 682 else 683 { 684 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: ETC not supported.\n"); 685 return PVR_FAIL; 686 } 687 } 688 } 689#endif 690 } 691 692 //Check for BGRA support. 693 if(eTextureFormat==GL_BGRA) 694 { 695#ifdef TARGET_OS_IPHONE 696 eTextureInternalFormat = GL_RGBA; 697#endif 698 if(!bIsBGRA8888Supported) 699 { 700#ifdef TARGET_OS_IPHONE 701 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA texture as extension GL_APPLE_texture_format_BGRA8888 is unsupported.\n"); 702#else 703 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA texture as extension GL_IMG_texture_format_BGRA8888 is unsupported.\n"); 704#endif 705 return PVR_FAIL; 706 } 707 } 708 709 //Check for floating point textures 710 if (eTextureType==GL_HALF_FLOAT_OES) 711 { 712 if(!bIsFloat16Supported) 713 { 714 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_HALF_FLOAT_OES texture as extension GL_OES_texture_half_float is unsupported.\n"); 715 } 716 } 717 if (eTextureType==GL_FLOAT) 718 { 719 if(!bIsFloat32Supported) 720 { 721 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_FLOAT texture as extension GL_OES_texture_float is unsupported.\n"); 722 } 723 } 724 725 //Deal with unsupported texture formats 726 if (eTextureInternalFormat==0) 727 { 728 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type not supported.\n"); 729 return PVR_FAIL; 730 } 731 732 //PVR files are never row aligned. 733 glPixelStorei(GL_UNPACK_ALIGNMENT,1); 734 735 //Generate a texture 736 glGenTextures(1, texName); 737 738 //Initialise a texture target. 739 GLint eTarget=GL_TEXTURE_2D; 740 741 //A mix of arrays/cubes/depths are not permitted in OpenGL ES. Check. 742 if(sTextureHeader.u32NumFaces>1 || sTextureHeader.u32NumSurfaces>1 || sTextureHeader.u32Depth>1) 743 { 744 if((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32NumSurfaces>1)) 745 { 746 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of cubemaps are not supported by OpenGL ES 3.0\n"); 747 return PVR_FAIL; 748 } 749 else if((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32Depth>1)) 750 { 751 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: 3D Cubemap textures are not supported by OpenGL ES 3.0\n"); 752 return PVR_FAIL; 753 } 754 else if((sTextureHeader.u32NumSurfaces>1) && (sTextureHeader.u32Depth>1)) 755 { 756 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of 3D textures are not supported by OpenGL ES 3.0\n"); 757 return PVR_FAIL; 758 } 759 760 if(sTextureHeader.u32NumSurfaces>1) 761 { 762 // GL_TEXTURE_2D_ARRAY; 763 return PVR_FAIL; 764 } 765 else if(sTextureHeader.u32NumFaces>1) 766 { 767 eTarget = GL_TEXTURE_CUBE_MAP; 768 } 769 else if(sTextureHeader.u32Depth>1) 770 { 771 eTarget = GL_TEXTURE_3D_OES; 772 bUsesTexImage3D = true; 773 } 774 } 775 776 if(bUsesTexImage3D && !bIsTexture3DSupported) 777 { 778 return PVR_FAIL; 779 } 780 781 //Bind the texture 782 glBindTexture(eTarget, *texName); 783 784 if(glGetError()) 785 { 786 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glBindTexture() failed.\n"); 787 return PVR_FAIL; 788 } 789 790 //Initialise the current MIP size. 791 PVRTuint32 uiCurrentMIPSize=0; 792 793 //Loop through the faces 794 //Check if this is a cube map. 795 if(sTextureHeader.u32NumFaces>1) 796 { 797 eTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X; 798 } 799 800 //Initialise the width/height 801 PVRTuint32 u32MIPWidth = sTextureHeader.u32Width; 802 PVRTuint32 u32MIPHeight = sTextureHeader.u32Height; 803 804 //Temporary data to save on if statements within the load loops. 805 PVRTuint8* pTempData=NULL; 806 PVRTextureHeaderV3 *psTempHeader=NULL; 807 if (bIsCompressedFormat && !bIsCompressedFormatSupported) 808 { 809 pTempData=(PVRTuint8*)pDecompressedData; 810 psTempHeader=&sTextureHeaderDecomp; 811 } 812 else 813 { 814 pTempData=pTextureData; 815 psTempHeader=&sTextureHeader; 816 } 817 818 PVRTuint32 u32MIPDepth = 1; 819 if(bUsesTexImage3D) 820 { 821 if(psTempHeader->u32Depth>1) 822 { 823 u32MIPDepth = psTempHeader->u32Depth; //3d texture. 824 } 825 else 826 { 827 return PVR_FAIL; //2d arrays. 828 } 829 } 830 831 //Loop through all MIP levels. 832 if (bIsLegacyPVR) 833 { 834 //Temporary texture target. 835 GLint eTextureTarget=eTarget; 836 837 //Loop through all the faces. 838 for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) 839 { 840 //Loop through all the mip levels. 841 for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) 842 { 843 //Get the current MIP size. 844 uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); 845 846 if (uiMIPLevel>=nLoadFromLevel) 847 { 848 //Upload the texture 849 if(bUsesTexImage3D) 850 { 851 if(bIsCompressedFormat && bIsCompressedFormatSupported) 852 { 853 extensions.glCompressedTexImage3DOES(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); 854 } 855 else 856 { 857 extensions.glTexImage3DOES(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData); 858 } 859 } 860 else 861 { 862 if(bIsCompressedFormat && bIsCompressedFormatSupported) 863 { 864 glCompressedTexImage2D(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); 865 } 866 else 867 { 868 glTexImage2D(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); 869 } 870 } 871 } 872 pTempData+=uiCurrentMIPSize; 873 874 //Reduce the MIP Size. 875 u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); 876 u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); 877 } 878 879 //Increase the texture target. 880 eTextureTarget++; 881 882 //Reset the current MIP dimensions. 883 u32MIPWidth=psTempHeader->u32Width; 884 u32MIPHeight=psTempHeader->u32Height; 885 886 //Error check 887 if(glGetError()) 888 { 889 FREE(pDecompressedData); 890 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 891 return PVR_FAIL; 892 } 893 } 894 } 895 else 896 { 897 for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) 898 { 899 //Get the current MIP size. 900 uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); 901 902 GLint eTextureTarget=eTarget; 903 904 for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) 905 { 906 if (uiMIPLevel>=nLoadFromLevel) 907 { 908 //Upload the texture 909 if(bUsesTexImage3D) 910 { 911 //Upload the texture 912 if(bIsCompressedFormat && bIsCompressedFormatSupported) 913 { 914 extensions.glCompressedTexImage3DOES(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); 915 } 916 else 917 { 918 extensions.glTexImage3DOES(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData); 919 } 920 } 921 else 922 { 923 //Upload the texture 924 if(bIsCompressedFormat && bIsCompressedFormatSupported) 925 { 926 glCompressedTexImage2D(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); 927 } 928 else 929 { 930 glTexImage2D(eTextureTarget, uiMIPLevel - nLoadFromLevel, eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); 931 } 932 } 933 } 934 pTempData+=uiCurrentMIPSize; 935 eTextureTarget++; 936 } 937 938 //Reduce the MIP Size. 939 u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); 940 u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); 941 942 //Error check 943 if(glGetError()) 944 { 945 FREE(pDecompressedData); 946 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 947 return PVR_FAIL; 948 } 949 } 950 } 951 952 FREE(pDecompressedData); 953 954 if (eTarget!=GL_TEXTURE_2D) 955 { 956 eTarget=GL_TEXTURE_CUBE_MAP; 957 } 958 959 //Error check 960 if(glGetError()) 961 { 962 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); 963 return PVR_FAIL; 964 } 965 966 //Set Minification and Magnification filters according to whether MIP maps are present. 967 if(eTextureType==GL_FLOAT || eTextureType==GL_HALF_FLOAT_OES) 968 { 969 if(sTextureHeader.u32MIPMapCount==1) 970 { // Texture filter modes are limited to these for float textures 971 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 972 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 973 } 974 else 975 { 976 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 977 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 978 } 979 } 980 else 981 { 982 if(sTextureHeader.u32MIPMapCount==1) 983 { 984 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 985 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 986 } 987 else 988 { 989 glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 990 glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 991 } 992 } 993 994 if( (sTextureHeader.u32Width & (sTextureHeader.u32Width - 1)) | (sTextureHeader.u32Height & (sTextureHeader.u32Height - 1))) 995 { 996 /* 997 NPOT textures requires the wrap mode to be set explicitly to 998 GL_CLAMP_TO_EDGE or the texture will be inconsistent. 999 */ 1000 glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1001 glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1002 } 1003 else 1004 { 1005 glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); 1006 glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); 1007 } 1008 1009 //Error check 1010 if(glGetError()) 1011 { 1012 PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexParameter() failed.\n"); 1013 return PVR_FAIL; 1014 } 1015 1016 return PVR_SUCCESS; 1017} 1018 1019/*!*************************************************************************** 1020 @Function PVRTTextureLoadFromPVR 1021 @Input filename Filename of the .PVR file to load the texture from 1022 @Modified texName the OpenGL ES texture name as returned by glBindTexture 1023 @Modified psTextureHeader Pointer to a PVRTextureHeaderV3 struct. Modified to 1024 contain the header data of the returned texture Ignored if NULL. 1025 @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware. 1026 @Input nLoadFromLevel Which mip map level to start loading from (0=all) 1027 @Modified pMetaData If a valid map is supplied, this will return any and all 1028 MetaDataBlocks stored in the texture, organised by DevFourCC 1029 then identifier. Supplying NULL will ignore all MetaData. 1030 @Return PVR_SUCCESS on success 1031 @Description Allows textures to be stored in binary PVR files and loaded in. Can load parts of a 1032 mip mapped texture (i.e. skipping the highest detailed levels). 1033 Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR 1034 if mip maps are present, GL_LINEAR/GL_LINEAR otherwise. 1035*****************************************************************************/ 1036EPVRTError PVRTTextureLoadFromPVR( const char * const filename, 1037 GLuint * const texName, 1038 const void *psTextureHeader, 1039 bool bAllowDecompress, 1040 const unsigned int nLoadFromLevel, 1041 CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData) 1042{ 1043 //Attempt to open file. 1044 CPVRTResourceFile TexFile(filename); 1045 1046 //Check file opened successfully. 1047 if (!TexFile.IsOpen()) 1048 { 1049 return PVR_FAIL; 1050 } 1051 1052 //Header size. 1053 PVRTuint32 u32HeaderSize=0; 1054 1055 //Boolean whether to byte swap the texture data or not. 1056 bool bSwapDataEndianness=false; 1057 1058 //Texture header to check against. 1059 PVRTextureHeaderV3 sTextureHeader; 1060 1061 //The channel type for endian swapping. 1062 EPVRTVariableType u32CurrentChannelType=ePVRTVarTypeUnsignedByte; 1063 1064 //Check the first word of the file and see if it's equal to the current identifier (or reverse identifier) 1065 if(*(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT && *(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT_REV) 1066 { 1067 //Swap the header bytes if necessary. 1068 if(!PVRTIsLittleEndian()) 1069 { 1070 bSwapDataEndianness=true; 1071 PVRTuint32 u32HeaderSize=PVRTByteSwap32(*(PVRTuint32*)TexFile.DataPtr()); 1072 1073 for (PVRTuint32 i=0; i<u32HeaderSize; ++i) 1074 { 1075 PVRTByteSwap( (PVRTuint8*)( ( (PVRTuint32*)TexFile.DataPtr() )+i),sizeof(PVRTuint32) ); 1076 } 1077 } 1078 1079 //Get a pointer to the header. 1080 PVR_Texture_Header* sLegacyTextureHeader=(PVR_Texture_Header*)TexFile.DataPtr(); 1081 1082 //Set the header size. 1083 u32HeaderSize=sLegacyTextureHeader->dwHeaderSize; 1084 1085 //We only really need the channel type. 1086 PVRTuint64 tempFormat; 1087 EPVRTColourSpace tempColourSpace; 1088 bool tempIsPreMult; 1089 1090 //Map the enum to get the channel type. 1091 PVRTMapLegacyTextureEnumToNewFormat( (PVRTPixelType)( sLegacyTextureHeader->dwpfFlags&0xff),tempFormat,tempColourSpace, u32CurrentChannelType, tempIsPreMult); 1092 } 1093 // If the header file has a reverse identifier, then we need to swap endianness 1094 else if(*(PVRTuint32*)TexFile.DataPtr()==PVRTEX_CURR_IDENT_REV) 1095 { 1096 //Setup the texture header 1097 sTextureHeader=*(PVRTextureHeaderV3*)TexFile.DataPtr(); 1098 1099 bSwapDataEndianness=true; 1100 PVRTextureHeaderV3* pTextureHeader=(PVRTextureHeaderV3*)TexFile.DataPtr(); 1101 1102 pTextureHeader->u32ChannelType=PVRTByteSwap32(pTextureHeader->u32ChannelType); 1103 pTextureHeader->u32ColourSpace=PVRTByteSwap32(pTextureHeader->u32ColourSpace); 1104 pTextureHeader->u32Depth=PVRTByteSwap32(pTextureHeader->u32Depth); 1105 pTextureHeader->u32Flags=PVRTByteSwap32(pTextureHeader->u32Flags); 1106 pTextureHeader->u32Height=PVRTByteSwap32(pTextureHeader->u32Height); 1107 pTextureHeader->u32MetaDataSize=PVRTByteSwap32(pTextureHeader->u32MetaDataSize); 1108 pTextureHeader->u32MIPMapCount=PVRTByteSwap32(pTextureHeader->u32MIPMapCount); 1109 pTextureHeader->u32NumFaces=PVRTByteSwap32(pTextureHeader->u32NumFaces); 1110 pTextureHeader->u32NumSurfaces=PVRTByteSwap32(pTextureHeader->u32NumSurfaces); 1111 pTextureHeader->u32Version=PVRTByteSwap32(pTextureHeader->u32Version); 1112 pTextureHeader->u32Width=PVRTByteSwap32(pTextureHeader->u32Width); 1113 PVRTByteSwap((PVRTuint8*)&pTextureHeader->u64PixelFormat,sizeof(PVRTuint64)); 1114 1115 //Channel type. 1116 u32CurrentChannelType=(EPVRTVariableType)pTextureHeader->u32ChannelType; 1117 1118 //Header size. 1119 u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 1120 } 1121 else 1122 { 1123 //Header size. 1124 u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; 1125 } 1126 1127 // Convert the data if needed 1128 if(bSwapDataEndianness) 1129 { 1130 //Get the size of the variables types. 1131 PVRTuint32 ui32VariableSize=0; 1132 switch(u32CurrentChannelType) 1133 { 1134 case ePVRTVarTypeFloat: 1135 case ePVRTVarTypeUnsignedInteger: 1136 case ePVRTVarTypeUnsignedIntegerNorm: 1137 case ePVRTVarTypeSignedInteger: 1138 case ePVRTVarTypeSignedIntegerNorm: 1139 { 1140 ui32VariableSize=4; 1141 break; 1142 } 1143 case ePVRTVarTypeUnsignedShort: 1144 case ePVRTVarTypeUnsignedShortNorm: 1145 case ePVRTVarTypeSignedShort: 1146 case ePVRTVarTypeSignedShortNorm: 1147 { 1148 ui32VariableSize=2; 1149 break; 1150 } 1151 case ePVRTVarTypeUnsignedByte: 1152 case ePVRTVarTypeUnsignedByteNorm: 1153 case ePVRTVarTypeSignedByte: 1154 case ePVRTVarTypeSignedByteNorm: 1155 { 1156 ui32VariableSize=1; 1157 break; 1158 } 1159 default: 1160 break; 1161 } 1162 1163 //If the size of the variable type is greater than 1, then we need to byte swap. 1164 if (ui32VariableSize>1) 1165 { 1166 //Get the texture data. 1167 PVRTuint8* pu8OrigData = ( (PVRTuint8*)TexFile.DataPtr() + u32HeaderSize); 1168 1169 //Get the size of the texture data. 1170 PVRTuint32 ui32TextureDataSize = PVRTGetTextureDataSize(sTextureHeader); 1171 1172 //Loop through and byte swap all the data. It's swapped in place so no need to do anything special. 1173 for(PVRTuint32 i = 0; i < ui32TextureDataSize; i+=ui32VariableSize) 1174 { 1175 PVRTByteSwap(pu8OrigData+i,ui32VariableSize); 1176 } 1177 } 1178 } 1179 1180 return PVRTTextureLoadFromPointer(TexFile.DataPtr(), texName, psTextureHeader, bAllowDecompress, nLoadFromLevel,NULL,pMetaData); 1181} 1182 1183/*!*************************************************************************** 1184 @Function PVRTTextureFormatGetBPP 1185 @Input nFormat 1186 @Input nType 1187 @Description Returns the bits per pixel (BPP) of the format. 1188*****************************************************************************/ 1189unsigned int PVRTTextureFormatGetBPP(const GLuint nFormat, const GLuint nType) 1190{ 1191 switch(nFormat) 1192 { 1193 case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 1194 case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 1195 return 2; 1196 case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 1197 case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 1198 return 4; 1199 case GL_UNSIGNED_BYTE: 1200 switch(nType) 1201 { 1202 case GL_RGBA: 1203 case GL_BGRA: 1204 return 32; 1205 } 1206 case GL_UNSIGNED_SHORT_5_5_5_1: 1207 switch(nType) 1208 { 1209 case GL_RGBA: 1210 return 16; 1211 } 1212 } 1213 1214 return 0xFFFFFFFF; 1215} 1216 1217/***************************************************************************** 1218 End of file (PVRTTextureAPI.cpp) 1219*****************************************************************************/ 1220 1221