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