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 *************************************************************************/
PVRTGetOGLES2TextureFormat(const PVRTextureHeaderV3 & sTextureHeader,PVRTuint32 & internalformat,PVRTuint32 & format,PVRTuint32 & type)47 static 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 *****************************************************************************/
PVRTTextureTile(PVRTextureHeaderV3 ** pOut,const PVRTextureHeaderV3 * const pIn,const int nRepeatCnt)267 void 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 *****************************************************************************/
PVRTTextureLoadFromPointer(const void * pointer,GLuint * const texName,const void * psTextureHeader,bool bAllowDecompress,const unsigned int nLoadFromLevel,const void * const texPtr,CPVRTMap<unsigned int,CPVRTMap<unsigned int,MetaDataBlock>> * pMetaData)340 EPVRTError 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 *****************************************************************************/
PVRTTextureLoadFromPVR(const char * const filename,GLuint * const texName,const void * psTextureHeader,bool bAllowDecompress,const unsigned int nLoadFromLevel,CPVRTMap<unsigned int,CPVRTMap<unsigned int,MetaDataBlock>> * pMetaData)1036 EPVRTError 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 *****************************************************************************/
PVRTTextureFormatGetBPP(const GLuint nFormat,const GLuint nType)1189 unsigned 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