• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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