|  | /****************************************************************************** | 
|  |  | 
|  | @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) | 
|  | *****************************************************************************/ | 
|  |  |