| /****************************************************************************** | 
 |  | 
 |  @File         OGLES3/PVRTTextureAPI.cpp | 
 |  | 
 |  @Title        OGLES3/PVRTTextureAPI | 
 |  | 
 |  @Version       | 
 |  | 
 |  @Copyright    Copyright (c) Imagination Technologies Limited. | 
 |  | 
 |  @Platform     ANSI compatible | 
 |  | 
 |  @Description  OGLES3 texture loading. | 
 |  | 
 | ******************************************************************************/ | 
 |  | 
 | #include <string.h> | 
 | #include <stdlib.h> | 
 |  | 
 | #include "PVRTContext.h" | 
 | #include "PVRTgles3Ext.h" | 
 | #include "PVRTTexture.h" | 
 | #include "PVRTTextureAPI.h" | 
 | #include "PVRTDecompress.h" | 
 | #include "PVRTFixedPoint.h" | 
 | #include "PVRTMap.h" | 
 | #include "PVRTMatrix.h" | 
 | #include "PVRTMisc.h" | 
 | #include "PVRTResourceFile.h" | 
 |  | 
 | /***************************************************************************** | 
 | ** Functions | 
 | ****************************************************************************/ | 
 |  | 
 | /*!*********************************************************************** | 
 | 	@Function:		PVRTGetOGLES3TextureFormat | 
 | 	@Input:			sTextureHeader | 
 | 	@Modified:		glInternalFormat | 
 | 	@Modified:		glFormat | 
 | 	@Modified:		glType | 
 | 	@Description:	Gets the OpenGLES equivalent values of internal format,  | 
 | 					format and type for this texture header. This will return  | 
 | 					any supported OpenGLES texture values, it is up to the user  | 
 | 					to decide if these are valid for their current platform. | 
 | *************************************************************************/ | 
 | static const void PVRTGetOGLES3TextureFormat(const PVRTextureHeaderV3& sTextureHeader, PVRTuint32& glInternalFormat, PVRTuint32& glFormat, PVRTuint32& glType) | 
 | {	 | 
 | 	PVRTuint64 PixelFormat = sTextureHeader.u64PixelFormat; | 
 | 	EPVRTVariableType ChannelType = (EPVRTVariableType)sTextureHeader.u32ChannelType; | 
 | 	EPVRTColourSpace ColourSpace = (EPVRTColourSpace)sTextureHeader.u32ColourSpace; | 
 |  | 
 | 	//Initialisation. Any invalid formats will return 0 always. | 
 | 	glFormat = 0; | 
 | 	glType = 0; | 
 | 	glInternalFormat=0; | 
 |  | 
 | 	//Get the last 32 bits of the pixel format. | 
 | 	PVRTuint64 PixelFormatPartHigh = PixelFormat&PVRTEX_PFHIGHMASK; | 
 |  | 
 | 	//Check for a compressed format (The first 8 bytes will be 0, so the whole thing will be equal to the last 32 bits). | 
 | 	if (PixelFormatPartHigh==0) | 
 | 	{ | 
 | 		//Format and type == 0 for compressed textures. | 
 | 		switch (PixelFormat) | 
 | 		{ | 
 | 		case ePVRTPF_PVRTCI_2bpp_RGB: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_PVRTCI_2bpp_RGBA: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_PVRTCI_4bpp_RGB: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_PVRTCI_4bpp_RGBA: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | #ifndef TARGET_OS_IPHONE | 
 | 		case ePVRTPF_PVRTCII_2bpp: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_PVRTCII_4bpp: | 
 | 			{ | 
 | 				if (ColourSpace == ePVRTCSpacesRGB) | 
 | 				{ | 
 | 					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_ETC1: | 
 | 			{ | 
 | 				glInternalFormat=GL_ETC1_RGB8_OES; | 
 | 				return; | 
 | 			} | 
 | #endif | 
 | 		case ePVRTPF_ETC2_RGB: | 
 | 			{ | 
 | 				if (ColourSpace==ePVRTCSpacesRGB) | 
 | 					glInternalFormat=GL_COMPRESSED_SRGB8_ETC2; | 
 | 				else | 
 | 					glInternalFormat=GL_COMPRESSED_RGB8_ETC2; | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_ETC2_RGBA: | 
 | 			{ | 
 | 				if (ColourSpace==ePVRTCSpacesRGB) | 
 | 					glInternalFormat=GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; | 
 | 				else | 
 | 					glInternalFormat=GL_COMPRESSED_RGBA8_ETC2_EAC; | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_ETC2_RGB_A1: | 
 | 			{ | 
 | 				if (ColourSpace==ePVRTCSpacesRGB) | 
 | 					glInternalFormat=GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; | 
 | 				else | 
 | 					glInternalFormat=GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_EAC_R11: | 
 | 			{ | 
 | 				if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedFloat) | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_SIGNED_R11_EAC; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_R11_EAC; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		case ePVRTPF_EAC_RG11: | 
 | 			{ | 
 | 				if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm ||  | 
 | 					ChannelType==ePVRTVarTypeSignedFloat) | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_SIGNED_RG11_EAC; | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					glInternalFormat=GL_COMPRESSED_RG11_EAC; | 
 | 				} | 
 | 				return; | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		switch (ChannelType) | 
 | 		{ | 
 | 		case ePVRTVarTypeUnsignedFloat: | 
 | 			if (PixelFormat==PVRTGENPIXELID3('r','g','b',11,11,10) ) | 
 | 			{ | 
 | 				glType=GL_UNSIGNED_INT_10F_11F_11F_REV; | 
 | 				glFormat = GL_RGB; | 
 | 				glInternalFormat=GL_R11F_G11F_B10F; | 
 | 				return; | 
 | 			} | 
 | 			break; | 
 | 		case ePVRTVarTypeSignedFloat: | 
 | 			{ | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 					//HALF_FLOAT | 
 | 				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_RGBA; | 
 | 						glInternalFormat=GL_RGBA; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',16,16,16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_RGB; | 
 | 						glInternalFormat=GL_RGB16F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',16,16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_RG; | 
 | 						glInternalFormat=GL_RG16F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_RED; | 
 | 						glInternalFormat=GL_R16F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('l','a',16,16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_LUMINANCE_ALPHA; | 
 | 						glInternalFormat=GL_LUMINANCE_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('l',16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_LUMINANCE; | 
 | 						glInternalFormat=GL_LUMINANCE; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('a',16): | 
 | 					{ | 
 | 						glType=GL_HALF_FLOAT; | 
 | 						glFormat = GL_ALPHA; | 
 | 						glInternalFormat=GL_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 					//FLOAT | 
 | 				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_RGBA; | 
 | 						glInternalFormat=GL_RGBA32F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',32,32,32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_RGB; | 
 | 						glInternalFormat=GL_RGB32F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',32,32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_RG; | 
 | 						glInternalFormat=GL_RG32F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_RED; | 
 | 						glInternalFormat=GL_R32F; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('l','a',32,32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_LUMINANCE_ALPHA; | 
 | 						glInternalFormat=GL_LUMINANCE_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('l',32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_LUMINANCE; | 
 | 						glInternalFormat=GL_LUMINANCE; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('a',32): | 
 | 					{ | 
 | 						glType=GL_FLOAT; | 
 | 						glFormat = GL_ALPHA; | 
 | 						glInternalFormat=GL_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedByteNorm: | 
 | 			{ | 
 | 				glType = GL_UNSIGNED_BYTE; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGBA; | 
 | 						if (ColourSpace==ePVRTCSpacesRGB) | 
 | 							glInternalFormat=GL_SRGB8_ALPHA8; | 
 | 						else | 
 | 							glInternalFormat=GL_RGBA8; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGB; | 
 | 						if (ColourSpace==ePVRTCSpacesRGB) | 
 | 							glInternalFormat=GL_SRGB8; | 
 | 						else | 
 | 							glInternalFormat=GL_RGB8; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',8,8): | 
 | 					{ | 
 | 						glFormat = GL_RG; | 
 | 						glInternalFormat=GL_RG8; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',8): | 
 | 					{ | 
 | 						glFormat = GL_RED; | 
 | 						glInternalFormat=GL_R8; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('l','a',8,8): | 
 | 					{ | 
 | 						glFormat = GL_LUMINANCE_ALPHA; | 
 | 						glInternalFormat=GL_LUMINANCE_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('l',8): | 
 | 					{ | 
 | 						glFormat = GL_LUMINANCE; | 
 | 						glInternalFormat=GL_LUMINANCE; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('a',8): | 
 | 					{ | 
 | 						glFormat = GL_ALPHA; | 
 | 						glInternalFormat=GL_ALPHA; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID4('b','g','r','a',8,8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_BGRA_EXT; | 
 | 						glInternalFormat=GL_BGRA_EXT; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeSignedByteNorm: | 
 | 			{ | 
 | 				glType = GL_BYTE; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGBA; | 
 | 						glInternalFormat=GL_RGBA8_SNORM; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGB; | 
 | 						glInternalFormat=GL_RGB8_SNORM; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',8,8): | 
 | 					{ | 
 | 						glFormat = GL_RG; | 
 | 						glInternalFormat=GL_RGB8_SNORM; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',8): | 
 | 					{ | 
 | 						glFormat = GL_RED; | 
 | 						glInternalFormat=GL_R8_SNORM; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedByte: | 
 | 			{ | 
 | 				glType = GL_UNSIGNED_BYTE; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA8UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB8UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',8,8): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG8UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',8): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R8UI; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeSignedByte: | 
 | 			{ | 
 | 				glType = GL_BYTE; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA8I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',8,8,8): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB8I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',8,8): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG8I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',8): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R8I; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedShortNorm: | 
 | 			{ | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',4,4,4,4): | 
 | 					{ | 
 | 						glType = GL_UNSIGNED_SHORT_4_4_4_4; | 
 | 						glFormat = GL_RGBA; | 
 | 						glInternalFormat=GL_RGBA4; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID4('r','g','b','a',5,5,5,1): | 
 | 					{ | 
 | 						glType = GL_UNSIGNED_SHORT_5_5_5_1; | 
 | 						glFormat = GL_RGBA; | 
 | 						glInternalFormat=GL_RGB5_A1; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',5,6,5): | 
 | 					{ | 
 | 						glType = GL_UNSIGNED_SHORT_5_6_5; | 
 | 						glFormat = GL_RGB; | 
 | 						glInternalFormat=GL_RGB565; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedShort: | 
 | 			{ | 
 | 				glType = GL_UNSIGNED_SHORT; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA16UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',16,16,16): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB16UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',16,16): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG16UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',16): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R16UI; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeSignedShort: | 
 | 			{ | 
 | 				glType = GL_SHORT; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA16I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',16,16,16): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB16I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',16,16): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG16I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',16): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R16I; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedIntegerNorm: | 
 | 			{ | 
 | 				if (PixelFormat==PVRTGENPIXELID4('a','b','g','r',2,10,10,10)) | 
 | 				{ | 
 | 					glType = GL_UNSIGNED_INT_2_10_10_10_REV; | 
 | 					glFormat = GL_RGBA; | 
 | 					glInternalFormat=GL_RGB10_A2; | 
 | 					return; | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedInteger: | 
 | 			{ | 
 | 				glType = GL_UNSIGNED_INT; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA32UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',32,32,32): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB32UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',32,32): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG32UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',32): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R32UI; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID4('a','b','g','r',2,10,10,10): | 
 | 					{ | 
 | 						glType = GL_UNSIGNED_INT_2_10_10_10_REV; | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGB10_A2UI; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeSignedInteger: | 
 | 			{ | 
 | 				glType = GL_INT; | 
 | 				switch (PixelFormat) | 
 | 				{ | 
 | 				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32): | 
 | 					{ | 
 | 						glFormat = GL_RGBA_INTEGER; | 
 | 						glInternalFormat=GL_RGBA32I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID3('r','g','b',32,32,32): | 
 | 					{ | 
 | 						glFormat = GL_RGB_INTEGER; | 
 | 						glInternalFormat=GL_RGB32I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID2('r','g',32,32): | 
 | 					{ | 
 | 						glFormat = GL_RG_INTEGER; | 
 | 						glInternalFormat=GL_RG32I; | 
 | 						return; | 
 | 					} | 
 | 				case PVRTGENPIXELID1('r',32): | 
 | 					{ | 
 | 						glFormat = GL_RED_INTEGER; | 
 | 						glInternalFormat=GL_R32I; | 
 | 						return; | 
 | 					} | 
 | 				} | 
 | 				break; | 
 | 			} | 
 | 		default: { } | 
 | 		} | 
 | 	} | 
 |  | 
 | 	//Default (erroneous) return values. | 
 | 	glType = glFormat = glInternalFormat = 0; | 
 | } | 
 |  | 
 |  | 
 | /*!*************************************************************************** | 
 | @Function		PVRTTextureTile | 
 | @Modified		pOut		The tiled texture in system memory | 
 | @Input			pIn			The source texture | 
 | @Input			nRepeatCnt	Number of times to repeat the source texture | 
 | @Description	Allocates and fills, in system memory, a texture large enough | 
 | 				to repeat the source texture specified number of times. | 
 | *****************************************************************************/ | 
 | void PVRTTextureTile( | 
 | 	PVRTextureHeaderV3			**pOut, | 
 | 	const PVRTextureHeaderV3	* const pIn, | 
 | 	const int					nRepeatCnt) | 
 | { | 
 | 	unsigned int		nFormat = 0, nType = 0, nBPP, nSize, nElW = 0, nElH = 0, nElD = 0; | 
 | 	PVRTuint8		*pMmSrc, *pMmDst; | 
 | 	unsigned int		nLevel; | 
 | 	PVRTextureHeaderV3	*psTexHeaderNew; | 
 |  | 
 | 	_ASSERT(pIn->u32Width); | 
 | 	_ASSERT(pIn->u32Width == pIn->u32Height); | 
 | 	_ASSERT(nRepeatCnt > 1); | 
 |  | 
 | 	PVRTGetOGLES3TextureFormat(*pIn,nFormat,nFormat,nType); | 
 | 	PVRTGetFormatMinDims(pIn->u64PixelFormat,nElW,nElH,nElD); | 
 | 	 | 
 | 	nBPP = PVRTGetBitsPerPixel(pIn->u64PixelFormat); | 
 | 	nSize = pIn->u32Width * nRepeatCnt; | 
 |  | 
 | 	psTexHeaderNew	= PVRTTextureCreate(nSize, nSize, nElW, nElH, nBPP, true); | 
 | 	*psTexHeaderNew	= *pIn; | 
 | 	pMmDst	= (PVRTuint8*)psTexHeaderNew + sizeof(*psTexHeaderNew); | 
 | 	pMmSrc	= (PVRTuint8*)pIn + sizeof(*pIn); | 
 |  | 
 | 	for(nLevel = 0; ((unsigned int)1 << nLevel) < nSize; ++nLevel) | 
 | 	{ | 
 | 		int nBlocksDstW = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElW); | 
 | 		int nBlocksDstH = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElH); | 
 | 		int nBlocksSrcW = PVRT_MAX((unsigned int)1, (pIn->u32Width >> nLevel) / nElW); | 
 | 		int nBlocksSrcH = PVRT_MAX((unsigned int)1, (pIn->u32Height >> nLevel) / nElH); | 
 | 		int nBlocksS	= nBPP * nElW * nElH / 8; | 
 |  | 
 | 		PVRTTextureLoadTiled( | 
 | 			pMmDst, | 
 | 			nBlocksDstW, | 
 | 			nBlocksDstH, | 
 | 			pMmSrc, | 
 | 			nBlocksSrcW, | 
 | 			nBlocksSrcH, | 
 | 			nBlocksS, | 
 | 			(pIn->u64PixelFormat>=ePVRTPF_PVRTCI_2bpp_RGB && pIn->u64PixelFormat<=ePVRTPF_PVRTCI_4bpp_RGBA) ? true : false); | 
 |  | 
 | 		pMmDst += nBlocksDstW * nBlocksDstH * nBlocksS; | 
 | 		pMmSrc += nBlocksSrcW * nBlocksSrcH * nBlocksS; | 
 | 	} | 
 |  | 
 | 	psTexHeaderNew->u32Width = nSize; | 
 | 	psTexHeaderNew->u32Height = nSize; | 
 | 	psTexHeaderNew->u32MIPMapCount = nLevel+1; | 
 | 	*pOut = psTexHeaderNew; | 
 | } | 
 |  | 
 | /*!*************************************************************************** | 
 |  @Function		PVRTTextureLoadFromPointer | 
 |  @Input			pointer				Pointer to header-texture's structure | 
 |  @Modified		texName				the OpenGL ES texture name as returned by glBindTexture | 
 |  @Modified		psTextureHeader		Pointer to a PVRTextureHeaderV3 struct. Modified to | 
 | 									contain the header data of the returned texture Ignored if NULL. | 
 |  @Input			bAllowDecompress	Allow decompression if PVRTC is not supported in hardware. | 
 |  @Input			nLoadFromLevel		Which mip map level to start loading from (0=all) | 
 |  @Input			texPtr				If null, texture follows header, else texture is here. | 
 |  @Modified		pMetaData			If a valid map is supplied, this will return any and all  | 
 | 									MetaDataBlocks stored in the texture, organised by DevFourCC | 
 | 									then identifier. Supplying NULL will ignore all MetaData. | 
 |  @Return		PVR_SUCCESS on success | 
 |  @Description	Allows textures to be stored in C header files and loaded in. Can load parts of a | 
 | 				mip mapped texture (i.e. skipping the highest detailed levels). In OpenGL Cube Map, each | 
 | 				texture's up direction is defined as next (view direction, up direction), | 
 | 				(+x,-y)(-x,-y)(+y,+z)(-y,-z)(+z,-y)(-z,-y). | 
 | 				Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR | 
 | 				if mip maps are present, GL_LINEAR/GL_LINEAR otherwise. | 
 | *****************************************************************************/ | 
 | EPVRTError 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) | 
 | { | 
 | 	//Compression bools | 
 | 	bool bIsCompressedFormatSupported=false; | 
 | 	bool bIsCompressedFormat=false; | 
 | 	bool bIsLegacyPVR=false; | 
 | 	bool bUsesTexImage3D=false; | 
 |  | 
 | 	//Texture setup | 
 | 	PVRTextureHeaderV3 sTextureHeader; | 
 | 	PVRTuint8* pTextureData=NULL; | 
 |  | 
 | 	//Just in case header and pointer for decompression. | 
 | 	PVRTextureHeaderV3 sTextureHeaderDecomp; | 
 | 	void* pDecompressedData=NULL; | 
 |  | 
 | 	//Check if it's an old header format | 
 | 	if((*(PVRTuint32*)pointer)!=PVRTEX3_IDENT) | 
 | 	{ | 
 | 		//Convert the texture header to the new format. | 
 | 		PVRTConvertOldTextureHeaderToV3((PVR_Texture_Header*)pointer,sTextureHeader,pMetaData); | 
 |  | 
 | 		//Get the texture data. | 
 | 		pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+*(PVRTuint32*)pointer; | 
 |  | 
 | 		bIsLegacyPVR=true; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		//Get the header from the main pointer. | 
 | 		sTextureHeader=*(PVRTextureHeaderV3*)pointer; | 
 |  | 
 | 		//Get the texture data. | 
 | 		pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; | 
 |  | 
 | 		if (pMetaData) | 
 | 		{ | 
 | 			//Read in all the meta data. | 
 | 			PVRTuint32 metaDataSize=0; | 
 | 			while (metaDataSize<sTextureHeader.u32MetaDataSize) | 
 | 			{ | 
 | 				//Read the DevFourCC and advance the pointer offset. | 
 | 				PVRTuint32 DevFourCC=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); | 
 | 				metaDataSize+=sizeof(DevFourCC); | 
 |  | 
 | 				//Read the Key and advance the pointer offset. | 
 | 				PVRTuint32 u32Key=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); | 
 | 				metaDataSize+=sizeof(u32Key); | 
 |  | 
 | 				//Read the DataSize and advance the pointer offset. | 
 | 				PVRTuint32 u32DataSize = *(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize); | 
 | 				metaDataSize+=sizeof(u32DataSize); | 
 |  | 
 | 				//Get the current meta data. | 
 | 				MetaDataBlock& currentMetaData = (*pMetaData)[DevFourCC][u32Key]; | 
 |  | 
 | 				//Assign the values to the meta data. | 
 | 				currentMetaData.DevFOURCC=DevFourCC; | 
 | 				currentMetaData.u32Key=u32Key; | 
 | 				currentMetaData.u32DataSize=u32DataSize; | 
 | 				 | 
 | 				//Check for data, if there is any, read it into the meta data. | 
 | 				if(u32DataSize > 0) | 
 | 				{ | 
 | 					//Allocate memory. | 
 | 					currentMetaData.Data = new PVRTuint8[u32DataSize]; | 
 |  | 
 | 					//Copy the data. | 
 | 					memcpy(currentMetaData.Data, ((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize), u32DataSize); | 
 |  | 
 | 					//Advance the meta data size. | 
 | 					metaDataSize+=u32DataSize; | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	//Return the PVRTextureHeader. | 
 | 	if (psTextureHeader) | 
 | 	{ | 
 | 		*(PVRTextureHeaderV3*)psTextureHeader=sTextureHeader; | 
 | 	} | 
 | 	 | 
 | 	//Setup GL Texture format values. | 
 | 	GLenum eTextureFormat = 0; | 
 | 	GLenum eTextureInternalFormat = 0;	// often this is the same as textureFormat, but not for BGRA8888 on iOS, for instance | 
 | 	GLenum eTextureType = 0; | 
 |  | 
 | 	//Get the OGLES format values. | 
 | 	PVRTGetOGLES3TextureFormat(sTextureHeader,eTextureInternalFormat,eTextureFormat,eTextureType); | 
 |  | 
 | 	bool bIsPVRTCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc"); | 
 | #ifndef TARGET_OS_IPHONE | 
 | 	bool bIsBGRA8888Supported  = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_format_BGRA8888"); | 
 | #else | 
 | 	bool bIsBGRA8888Supported  = CPVRTgles3Ext::IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888"); | 
 | #endif	 | 
 | #ifndef TARGET_OS_IPHONE | 
 | 	bool bIsETCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_OES_compressed_ETC1_RGB8_texture"); | 
 | #endif | 
 | 		 | 
 | 	//Check for compressed formats | 
 | 	if (eTextureFormat==0 && eTextureType==0 && eTextureInternalFormat!=0) | 
 | 	{ | 
 | 		if (eTextureInternalFormat>=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG && eTextureInternalFormat<=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG) | 
 | 		{ | 
 | 			//Check for PVRTCI support. | 
 | 			if(bIsPVRTCSupported) | 
 | 			{ | 
 | 				bIsCompressedFormatSupported = bIsCompressedFormat = true; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				//Try to decompress the texture. | 
 | 				if(bAllowDecompress) | 
 | 				{ | 
 | 					//Output a warning. | 
 | 					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC not supported. Converting to RGBA8888 instead.\n"); | 
 |  | 
 | 					//Modify boolean values. | 
 | 					bIsCompressedFormatSupported = false; | 
 | 					bIsCompressedFormat = true; | 
 |  | 
 | 					//Check if it's 2bpp. | 
 | 					bool bIs2bppPVRTC = (eTextureInternalFormat==GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG || eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); | 
 |  | 
 | 					//Change texture format. | 
 | 					eTextureFormat = eTextureInternalFormat = GL_RGBA; | 
 | 					eTextureType = GL_UNSIGNED_BYTE; | 
 |  | 
 | 					//Create a near-identical texture header for the decompressed header. | 
 | 					sTextureHeaderDecomp = sTextureHeader; | 
 | 					sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; | 
 | 					sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; | 
 | 					sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); | 
 |  | 
 | 					//Allocate enough memory for the decompressed data. OGLES2, so only decompress one surface/face. | 
 | 					pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); | 
 |  | 
 | 					//Check the malloc. | 
 | 					if (!pDecompressedData) | 
 | 					{ | 
 | 						PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); | 
 | 						return PVR_FAIL; | 
 | 					} | 
 |  | 
 | 					//Get the dimensions for the current MIP level. | 
 | 					PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; | 
 | 					PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; | 
 |  | 
 | 					//Setup temporary variables. | 
 | 					PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; | 
 | 					PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; | 
 |  | 
 | 					if (bIsLegacyPVR) | 
 | 					{ | 
 | 						//Decompress all the MIP levels. | 
 | 						for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) | 
 | 						{ | 
 |  | 
 | 							for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) | 
 | 							{ | 
 | 								//Get the face offset. Varies per MIP level. | 
 | 								PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); | 
 | 								PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); | 
 |  | 
 | 								//Decompress the texture data. | 
 | 								PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); | 
 |  | 
 | 								//Move forward through the pointers. | 
 | 								pTempDecompData+=decompressedFaceOffset; | 
 | 								pTempCompData+=compressedFaceOffset; | 
 |  | 
 | 								//Work out the current MIP dimensions. | 
 | 								uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); | 
 | 								uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); | 
 | 							} | 
 |  | 
 | 							//Reset the dims. | 
 | 							uiMIPWidth=sTextureHeader.u32Width; | 
 | 							uiMIPHeight=sTextureHeader.u32Height; | 
 | 						} | 
 | 					} | 
 | 					else | 
 | 					{ | 
 | 						//Decompress all the MIP levels. | 
 | 						for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) | 
 | 						{ | 
 | 							//Get the face offset. Varies per MIP level. | 
 | 							PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); | 
 | 							PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); | 
 |  | 
 | 							for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) | 
 | 							{ | 
 | 								//Decompress the texture data. | 
 | 								PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData); | 
 |  | 
 | 								//Move forward through the pointers. | 
 | 								pTempDecompData+=decompressedFaceOffset; | 
 | 								pTempCompData+=compressedFaceOffset; | 
 | 							} | 
 |  | 
 | 							//Work out the current MIP dimensions. | 
 | 							uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); | 
 | 							uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC not supported.\n"); | 
 | 					return PVR_FAIL; | 
 | 				} | 
 | 			} | 
 | 		} | 
 | #ifndef TARGET_OS_IPHONE //TODO | 
 | 		else if (eTextureInternalFormat==GL_ETC1_RGB8_OES) | 
 | 		{ | 
 | 			if(bIsETCSupported) | 
 | 			{ | 
 | 				bIsCompressedFormatSupported = bIsCompressedFormat = true; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				if(bAllowDecompress) | 
 | 				{ | 
 | 					//Output a warning. | 
 | 					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: ETC not supported. Converting to RGBA8888 instead.\n"); | 
 |  | 
 | 					//Modify boolean values. | 
 | 					bIsCompressedFormatSupported = false; | 
 | 					bIsCompressedFormat = true; | 
 |  | 
 | 					//Change texture format. | 
 | 					eTextureFormat = eTextureInternalFormat = GL_RGBA; | 
 | 					eTextureType = GL_UNSIGNED_BYTE; | 
 |  | 
 | 					//Create a near-identical texture header for the decompressed header. | 
 | 					sTextureHeaderDecomp = sTextureHeader; | 
 | 					sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm; | 
 | 					sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB; | 
 | 					sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8); | 
 |  | 
 | 					//Allocate enough memory for the decompressed data. OGLES1, so only decompress one surface/face. | 
 | 					pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) ); | 
 |  | 
 | 					//Check the malloc. | 
 | 					if (!pDecompressedData) | 
 | 					{ | 
 | 						PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n"); | 
 | 						return PVR_FAIL; | 
 | 					} | 
 |  | 
 | 					//Get the dimensions for the current MIP level. | 
 | 					PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel; | 
 | 					PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel; | 
 |  | 
 | 					//Setup temporary variables. | 
 | 					PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData; | 
 | 					PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData; | 
 |  | 
 | 					if (bIsLegacyPVR) | 
 | 					{ | 
 | 						//Decompress all the MIP levels. | 
 | 						for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) | 
 | 						{ | 
 |  | 
 | 							for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) | 
 | 							{ | 
 | 								//Get the face offset. Varies per MIP level. | 
 | 								PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); | 
 | 								PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); | 
 |  | 
 | 								//Decompress the texture data. | 
 | 								PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); | 
 |  | 
 | 								//Move forward through the pointers. | 
 | 								pTempDecompData+=decompressedFaceOffset; | 
 | 								pTempCompData+=compressedFaceOffset; | 
 |  | 
 | 								//Work out the current MIP dimensions. | 
 | 								uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); | 
 | 								uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); | 
 | 							} | 
 |  | 
 | 							//Reset the dims. | 
 | 							uiMIPWidth=sTextureHeader.u32Width; | 
 | 							uiMIPHeight=sTextureHeader.u32Height; | 
 | 						} | 
 | 					} | 
 | 					else | 
 | 					{ | 
 | 						//Decompress all the MIP levels. | 
 | 						for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap) | 
 | 						{ | 
 | 							//Get the face offset. Varies per MIP level. | 
 | 							PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false); | 
 | 							PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false); | 
 |  | 
 | 							for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace) | 
 | 							{ | 
 | 								//Decompress the texture data. | 
 | 								PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0); | 
 |  | 
 | 								//Move forward through the pointers. | 
 | 								pTempDecompData+=decompressedFaceOffset; | 
 | 								pTempCompData+=compressedFaceOffset; | 
 | 							} | 
 |  | 
 | 							//Work out the current MIP dimensions. | 
 | 							uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1); | 
 | 							uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1); | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: ETC not supported.\n"); | 
 | 					return PVR_FAIL; | 
 | 				} | 
 | 			} | 
 | 		} | 
 | #endif | 
 | 	} | 
 |  | 
 | 	//Check for BGRA support.	 | 
 | 	if(eTextureFormat==GL_BGRA_IMG) | 
 | 	{ | 
 | #ifdef TARGET_OS_IPHONE | 
 | 		eTextureInternalFormat = GL_RGBA; | 
 | #endif | 
 | 		if(!bIsBGRA8888Supported) | 
 | 		{ | 
 | #ifdef TARGET_OS_IPHONE | 
 | 			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_APPLE_texture_format_BGRA8888 is unsupported.\n"); | 
 | #else | 
 | 			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_IMG_texture_format_BGRA8888 is unsupported.\n"); | 
 | #endif | 
 | 			return PVR_FAIL; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	//Deal with unsupported texture formats | 
 | 	if (eTextureInternalFormat==0) | 
 | 	{ | 
 | 		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type not supported.\n"); | 
 | 		return PVR_FAIL; | 
 | 	} | 
 |  | 
 | 	//PVR files are never row aligned. | 
 | 	glPixelStorei(GL_UNPACK_ALIGNMENT,1); | 
 |  | 
 | 	//Generate a texture | 
 | 	glGenTextures(1, texName); | 
 |  | 
 | 	//Initialise a texture target. | 
 | 	GLint eTarget=GL_TEXTURE_2D; | 
 |  | 
 | 	//A mix of arrays/cubes/depths are not permitted in OpenGL ES. Check. | 
 | 	if (sTextureHeader.u32NumFaces>1 || sTextureHeader.u32NumSurfaces>1 || sTextureHeader.u32Depth>1) | 
 | 	{ | 
 | 		if((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32NumSurfaces>1)) | 
 | 		{ | 
 | 			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of cubemaps are not supported by OpenGL ES 3.0\n"); | 
 | 			return PVR_FAIL; | 
 | 		} | 
 | 		else if ((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32Depth>1)) | 
 | 		{ | 
 | 			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: 3D Cubemap textures are not supported by OpenGL ES 3.0\n"); | 
 | 			return PVR_FAIL; | 
 | 		} | 
 | 		else if ((sTextureHeader.u32NumSurfaces>1) && (sTextureHeader.u32Depth>1)) | 
 | 		{ | 
 | 			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of 3D textures are not supported by OpenGL ES 3.0\n"); | 
 | 			return PVR_FAIL; | 
 | 		} | 
 |  | 
 | 		if(sTextureHeader.u32NumSurfaces>1) | 
 | 		{ | 
 | 			eTarget=GL_TEXTURE_2D_ARRAY; | 
 | 			bUsesTexImage3D=true; | 
 | 		} | 
 | 		else if(sTextureHeader.u32NumFaces>1) | 
 | 		{ | 
 | 			eTarget=GL_TEXTURE_CUBE_MAP; | 
 | 		} | 
 | 		else if (sTextureHeader.u32Depth>1) | 
 | 		{ | 
 | 			eTarget=GL_TEXTURE_3D; | 
 | 			bUsesTexImage3D=true; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	//Bind the texture | 
 | 	glBindTexture(eTarget, *texName); | 
 |  | 
 | 	if(glGetError()) | 
 | 	{ | 
 | 		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glBindTexture() failed.\n"); | 
 | 		return PVR_FAIL; | 
 | 	} | 
 |  | 
 | 	//Temporary data to save on if statements within the load loops. | 
 | 	PVRTuint8* pTempData=NULL; | 
 | 	PVRTextureHeaderV3 *psTempHeader=NULL; | 
 | 	if (bIsCompressedFormat && !bIsCompressedFormatSupported) | 
 | 	{ | 
 | 		pTempData=(PVRTuint8*)pDecompressedData; | 
 | 		psTempHeader=&sTextureHeaderDecomp; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		pTempData=pTextureData; | 
 | 		psTempHeader=&sTextureHeader; | 
 | 	} | 
 |  | 
 | 	//Initialise the current MIP size. | 
 | 	PVRTuint32 uiCurrentMIPSize=0; | 
 |  | 
 | 	//Initialise the width/height | 
 | 	PVRTuint32 u32MIPWidth = sTextureHeader.u32Width; | 
 | 	PVRTuint32 u32MIPHeight = sTextureHeader.u32Height; | 
 | 	PVRTuint32 u32MIPDepth; | 
 | 	if (psTempHeader->u32Depth>1) | 
 | 	{ | 
 | 		u32MIPDepth=psTempHeader->u32Depth; //3d texture. | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays. | 
 | 	} | 
 |  | 
 | 	//Loop through all MIP levels. | 
 | 	if (bIsLegacyPVR) | 
 | 	{ | 
 | 		//Temporary texture target. | 
 | 		GLint eTextureTarget=eTarget; | 
 |  | 
 | 		//Cubemaps are special. | 
 | 		if (eTextureTarget==GL_TEXTURE_CUBE_MAP) | 
 | 		{ | 
 | 			eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X; | 
 | 		} | 
 |  | 
 | 		//Loop through all the faces. | 
 | 		for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) | 
 | 		{ | 
 | 			//Loop through all the mip levels. | 
 | 			for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) | 
 | 			{ | 
 | 				//Get the current MIP size. | 
 | 				uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); | 
 |  | 
 | 				if (uiMIPLevel>=nLoadFromLevel) | 
 | 				{ | 
 | 					//Upload the texture | 
 | 					if (bUsesTexImage3D) | 
 | 					{ | 
 | 						if (bIsCompressedFormat && bIsCompressedFormatSupported) | 
 | 						{ | 
 | 							glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); | 
 | 						} | 
 | 						else | 
 | 						{ | 
 | 							glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth,  0, eTextureFormat, eTextureType, pTempData); | 
 | 						} | 
 | 					} | 
 | 					else | 
 | 					{ | 
 | 						if (bIsCompressedFormat && bIsCompressedFormatSupported) | 
 | 						{ | 
 | 							glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); | 
 | 						} | 
 | 						else | 
 | 						{ | 
 | 							glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 				pTempData+=uiCurrentMIPSize; | 
 |  | 
 | 				//Reduce the MIP Size. | 
 | 				u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); | 
 | 				u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); | 
 | 				if (psTempHeader->u32Depth>1) | 
 | 				{ | 
 | 					u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1); | 
 | 				} | 
 | 			} | 
 |  | 
 | 			//Increase the texture target. | 
 | 			eTextureTarget++; | 
 |  | 
 | 			//Reset the current MIP dimensions. | 
 | 			u32MIPWidth=psTempHeader->u32Width; | 
 | 			u32MIPHeight=psTempHeader->u32Height; | 
 |  | 
 | 			if (psTempHeader->u32Depth>1) | 
 | 			{ | 
 | 				u32MIPDepth=psTempHeader->u32Depth; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays. | 
 | 			} | 
 |  | 
 | 			//Error check | 
 | 			if(glGetError()) | 
 | 			{ | 
 | 				FREE(pDecompressedData); | 
 | 				PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); | 
 | 				return PVR_FAIL; | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel) | 
 | 		{ | 
 | 			//Get the current MIP size. | 
 | 			uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false); | 
 |  | 
 | 			GLint eTextureTarget=eTarget; | 
 | 			//Cubemaps are special. | 
 | 			if (eTextureTarget==GL_TEXTURE_CUBE_MAP) | 
 | 			{ | 
 | 				eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X; | 
 | 			} | 
 |  | 
 | 			for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace) | 
 | 			{ | 
 | 				if (uiMIPLevel>=nLoadFromLevel) | 
 | 				{ | 
 | 					//Upload the texture | 
 | 					if (bUsesTexImage3D) | 
 | 					{ | 
 | 						//Upload the texture | 
 | 						if (bIsCompressedFormat && bIsCompressedFormatSupported) | 
 | 						{ | 
 | 							glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData); | 
 | 						} | 
 | 						else | 
 | 						{ | 
 | 							glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData); | 
 | 						} | 
 | 					} | 
 | 					else | 
 | 					{ | 
 | 						//Upload the texture | 
 | 						if (bIsCompressedFormat && bIsCompressedFormatSupported) | 
 | 						{ | 
 | 							glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData); | 
 | 						} | 
 | 						else | 
 | 						{ | 
 | 							glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData); | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 				pTempData+=uiCurrentMIPSize; | 
 | 				eTextureTarget++; | 
 | 			} | 
 |  | 
 | 			//Reduce the MIP Size. | 
 | 			u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1); | 
 | 			u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1); | 
 | 			if (psTempHeader->u32Depth>1) | 
 | 			{ | 
 | 				u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1); //Only reduce depth for 3D textures, not texture arrays. | 
 | 			} | 
 |  | 
 | 			//Error check | 
 | 			if(glGetError()) | 
 | 			{ | 
 | 				FREE(pDecompressedData); | 
 | 				PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); | 
 | 				return PVR_FAIL; | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	FREE(pDecompressedData); | 
 |  | 
 | 	//Error check | 
 | 	if(glGetError()) | 
 | 	{ | 
 | 		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n"); | 
 | 		return PVR_FAIL; | 
 | 	} | 
 | 	 | 
 | 	//Set Minification and Magnification filters according to whether MIP maps are present. | 
 | 	if(eTextureType==GL_FLOAT || eTextureType==GL_HALF_FLOAT) | 
 | 	{ | 
 | 		if(sTextureHeader.u32MIPMapCount==1) | 
 | 		{	// Texture filter modes are limited to these for float textures | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		if(sTextureHeader.u32MIPMapCount==1) | 
 | 		{ | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); | 
 | 			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if(	(sTextureHeader.u32Width & (sTextureHeader.u32Width - 1)) | (sTextureHeader.u32Height & (sTextureHeader.u32Height - 1))) | 
 | 	{ | 
 | 		/* | 
 | 			NPOT textures requires the wrap mode to be set explicitly to | 
 | 			GL_CLAMP_TO_EDGE or the texture will be inconsistent. | 
 | 		*/ | 
 | 		glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
 | 		glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); | 
 | 		glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); | 
 | 	} | 
 |  | 
 | 	//Error check | 
 | 	if(glGetError()) | 
 | 	{ | 
 | 		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexParameter() failed.\n"); | 
 | 		return PVR_FAIL; | 
 | 	} | 
 |  | 
 | 	return PVR_SUCCESS; | 
 | } | 
 |  | 
 | /*!*************************************************************************** | 
 |  @Function		PVRTTextureLoadFromPVR | 
 |  @Input			filename			Filename of the .PVR file to load the texture from | 
 |  @Modified		texName				the OpenGL ES texture name as returned by glBindTexture | 
 |  @Modified		psTextureHeader		Pointer to a PVR_Texture_Header struct. Modified to | 
 | 									contain the header data of the returned texture Ignored if NULL. | 
 |  @Input			bAllowDecompress	Allow decompression if PVRTC is not supported in hardware. | 
 |  @Input			nLoadFromLevel		Which mipmap level to start loading from (0=all) | 
 |  @Modified		pMetaData			If a valid map is supplied, this will return any and all  | 
 | 									MetaDataBlocks stored in the texture, organised by DevFourCC | 
 | 									then identifier. Supplying NULL will ignore all MetaData. | 
 |  @Return		PVR_SUCCESS on success | 
 |  @Description	Allows textures to be stored in binary PVR files and loaded in. Can load parts of a | 
 | 				mipmaped texture (ie skipping the highest detailed levels). | 
 | 				Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR | 
 | 				if mipmaps are present, GL_LINEAR/GL_LINEAR otherwise. | 
 | *****************************************************************************/ | 
 | EPVRTError 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) | 
 | { | 
 | 	//Attempt to open file. | 
 | 	CPVRTResourceFile TexFile(filename); | 
 |  | 
 | 	//Check file opened successfully. | 
 | 	if (!TexFile.IsOpen())  | 
 | 	{ | 
 | 		return PVR_FAIL; | 
 | 	} | 
 |  | 
 | 	//Header size. | 
 | 	PVRTuint32 u32HeaderSize=0; | 
 |  | 
 | 	//Boolean whether to byte swap the texture data or not. | 
 | 	bool bSwapDataEndianness=false; | 
 |  | 
 | 	//Texture header to check against. | 
 | 	PVRTextureHeaderV3 sTextureHeader; | 
 |  | 
 | 	//The channel type for endian swapping. | 
 | 	EPVRTVariableType u32CurrentChannelType=ePVRTVarTypeUnsignedByte; | 
 |  | 
 | 	//Check the first word of the file and see if it's equal to the current identifier (or reverse identifier) | 
 | 	if(*(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT && *(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT_REV) | 
 | 	{ | 
 | 		//Swap the header bytes if necessary. | 
 | 		if(!PVRTIsLittleEndian()) | 
 | 		{ | 
 | 			bSwapDataEndianness=true; | 
 | 			PVRTuint32 u32HeaderSize=PVRTByteSwap32(*(PVRTuint32*)TexFile.DataPtr()); | 
 |  | 
 | 			for (PVRTuint32 i=0; i<u32HeaderSize; ++i) | 
 | 			{ | 
 | 				PVRTByteSwap( (PVRTuint8*)( ( (PVRTuint32*)TexFile.DataPtr() )+i),sizeof(PVRTuint32) ); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		//Get a pointer to the header. | 
 | 		PVR_Texture_Header* sLegacyTextureHeader=(PVR_Texture_Header*)TexFile.DataPtr(); | 
 |  | 
 | 		//Set the header size. | 
 | 		u32HeaderSize=sLegacyTextureHeader->dwHeaderSize; | 
 |  | 
 | 		//We only really need the channel type. | 
 | 		PVRTuint64 tempFormat; | 
 | 		EPVRTColourSpace tempColourSpace; | 
 | 		bool tempIsPreMult; | 
 |  | 
 | 		//Map the enum to get the channel type. | 
 | 		PVRTMapLegacyTextureEnumToNewFormat( (PVRTPixelType)( sLegacyTextureHeader->dwpfFlags&0xff),tempFormat,tempColourSpace, u32CurrentChannelType, tempIsPreMult); | 
 | 	} | 
 | 	// If the header file has a reverse identifier, then we need to swap endianness | 
 | 	else if(*(PVRTuint32*)TexFile.DataPtr()==PVRTEX_CURR_IDENT_REV) | 
 | 	{ | 
 | 		//Setup the texture header | 
 | 		sTextureHeader=*(PVRTextureHeaderV3*)TexFile.DataPtr(); | 
 |  | 
 | 		bSwapDataEndianness=true; | 
 | 		PVRTextureHeaderV3* pTextureHeader=(PVRTextureHeaderV3*)TexFile.DataPtr(); | 
 |  | 
 | 		pTextureHeader->u32ChannelType=PVRTByteSwap32(pTextureHeader->u32ChannelType); | 
 | 		pTextureHeader->u32ColourSpace=PVRTByteSwap32(pTextureHeader->u32ColourSpace); | 
 | 		pTextureHeader->u32Depth=PVRTByteSwap32(pTextureHeader->u32Depth); | 
 | 		pTextureHeader->u32Flags=PVRTByteSwap32(pTextureHeader->u32Flags); | 
 | 		pTextureHeader->u32Height=PVRTByteSwap32(pTextureHeader->u32Height); | 
 | 		pTextureHeader->u32MetaDataSize=PVRTByteSwap32(pTextureHeader->u32MetaDataSize); | 
 | 		pTextureHeader->u32MIPMapCount=PVRTByteSwap32(pTextureHeader->u32MIPMapCount); | 
 | 		pTextureHeader->u32NumFaces=PVRTByteSwap32(pTextureHeader->u32NumFaces); | 
 | 		pTextureHeader->u32NumSurfaces=PVRTByteSwap32(pTextureHeader->u32NumSurfaces); | 
 | 		pTextureHeader->u32Version=PVRTByteSwap32(pTextureHeader->u32Version); | 
 | 		pTextureHeader->u32Width=PVRTByteSwap32(pTextureHeader->u32Width); | 
 | 		PVRTByteSwap((PVRTuint8*)&pTextureHeader->u64PixelFormat,sizeof(PVRTuint64)); | 
 |  | 
 | 		//Channel type. | 
 | 		u32CurrentChannelType=(EPVRTVariableType)pTextureHeader->u32ChannelType; | 
 |  | 
 | 		//Header size. | 
 | 		u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		//Header size. | 
 | 		u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize; | 
 | 	} | 
 |  | 
 | 	// Convert the data if needed | 
 | 	if(bSwapDataEndianness) | 
 | 	{ | 
 | 		//Get the size of the variables types. | 
 | 		PVRTuint32 ui32VariableSize=0; | 
 | 		switch(u32CurrentChannelType) | 
 | 		{ | 
 | 		case ePVRTVarTypeFloat: | 
 | 		case ePVRTVarTypeUnsignedInteger: | 
 | 		case ePVRTVarTypeUnsignedIntegerNorm: | 
 | 		case ePVRTVarTypeSignedInteger: | 
 | 		case ePVRTVarTypeSignedIntegerNorm: | 
 | 			{ | 
 | 				ui32VariableSize=4; | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedShort: | 
 | 		case ePVRTVarTypeUnsignedShortNorm: | 
 | 		case ePVRTVarTypeSignedShort: | 
 | 		case ePVRTVarTypeSignedShortNorm: | 
 | 			{ | 
 | 				ui32VariableSize=2; | 
 | 				break; | 
 | 			} | 
 | 		case ePVRTVarTypeUnsignedByte: | 
 | 		case ePVRTVarTypeUnsignedByteNorm: | 
 | 		case ePVRTVarTypeSignedByte: | 
 | 		case ePVRTVarTypeSignedByteNorm: | 
 | 			{ | 
 | 				ui32VariableSize=1; | 
 | 				break; | 
 | 			} | 
 |         default: | 
 |             return PVR_FAIL; | 
 | 		} | 
 | 		 | 
 | 		//If the size of the variable type is greater than 1, then we need to byte swap. | 
 | 		if (ui32VariableSize>1) | 
 | 		{ | 
 | 			//Get the texture data. | 
 | 			PVRTuint8* pu8OrigData = ( (PVRTuint8*)TexFile.DataPtr() + u32HeaderSize); | 
 |  | 
 | 			//Get the size of the texture data. | 
 | 			PVRTuint32 ui32TextureDataSize = PVRTGetTextureDataSize(sTextureHeader); | 
 | 				 | 
 | 			//Loop through and byte swap all the data. It's swapped in place so no need to do anything special. | 
 | 			for(PVRTuint32 i = 0; i < ui32TextureDataSize; i+=ui32VariableSize) | 
 | 			{ | 
 | 				PVRTByteSwap(pu8OrigData+i,ui32VariableSize); | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	 | 
 | 	return PVRTTextureLoadFromPointer(TexFile.DataPtr(), texName, psTextureHeader, bAllowDecompress, nLoadFromLevel,NULL,pMetaData); | 
 | } | 
 |  | 
 | /***************************************************************************** | 
 |  End of file (PVRTTextureAPI.cpp) | 
 | *****************************************************************************/ | 
 |  |