Browse Source

Improved support for non-PVRTC compressed texture formats in .pvr files.

Alex Szpakowski 9 years ago
parent
commit
7265f891de
3 changed files with 118 additions and 11 deletions
  1. 2 2
      src/common/Variant.cpp
  2. 1 1
      src/common/Variant.h
  3. 115 8
      src/modules/image/magpie/PVRHandler.cpp

+ 2 - 2
src/common/Variant.cpp

@@ -165,7 +165,7 @@ Variant *Variant::fromLua(lua_State *L, int n, bool allowTables)
 		if (allowTables)
 		if (allowTables)
 		{
 		{
 			bool success = true;
 			bool success = true;
-			std::vector<std::pair<Variant*, Variant*> > *table = new std::vector<std::pair<Variant*, Variant*> >();
+			std::vector<std::pair<Variant*, Variant*>> *table = new std::vector<std::pair<Variant*, Variant*>>();
 			lua_pushnil(L);
 			lua_pushnil(L);
 			while (lua_next(L, n))
 			while (lua_next(L, n))
 			{
 			{
@@ -230,7 +230,7 @@ void Variant::toLua(lua_State *L)
 		// I can do (at the moment).
 		// I can do (at the moment).
 		break;
 		break;
 	case TABLE:
 	case TABLE:
-		lua_newtable(L);
+		lua_createtable(L, 0, (int) data.table->size());
 		for (size_t i = 0; i < data.table->size(); ++i)
 		for (size_t i = 0; i < data.table->size(); ++i)
 		{
 		{
 			std::pair<Variant*, Variant*> &kv = data.table->at(i);
 			std::pair<Variant*, Variant*> &kv = data.table->at(i);

+ 1 - 1
src/common/Variant.h

@@ -71,7 +71,7 @@ public:
 			size_t len;
 			size_t len;
 		} string;
 		} string;
 		void *userdata;
 		void *userdata;
-		std::vector<std::pair<Variant*, Variant*> > *table;
+		std::vector<std::pair<Variant*, Variant*>> *table;
 	} data;
 	} data;
 
 
 private:
 private:

+ 115 - 8
src/modules/image/magpie/PVRHandler.cpp

@@ -59,19 +59,59 @@ struct PVRTexHeaderV3
 
 
 enum PVRV3PixelFormat
 enum PVRV3PixelFormat
 {
 {
-	ePVRTPF_PVRTCI_2bpp_RGB = 0x00,
+	ePVRTPF_PVRTCI_2bpp_RGB = 0,
 	ePVRTPF_PVRTCI_2bpp_RGBA,
 	ePVRTPF_PVRTCI_2bpp_RGBA,
 	ePVRTPF_PVRTCI_4bpp_RGB,
 	ePVRTPF_PVRTCI_4bpp_RGB,
 	ePVRTPF_PVRTCI_4bpp_RGBA,
 	ePVRTPF_PVRTCI_4bpp_RGBA,
-	ePVRTPF_PVRTCII_2bpp,
+	ePVRTPF_PVRTCII_2bpp = 4,
 	ePVRTPF_PVRTCII_4bpp,
 	ePVRTPF_PVRTCII_4bpp,
-	ePVRTPF_ETC1 = 0x06,
-	ePVRTPF_DXT1,
+	ePVRTPF_ETC1 = 6,
+	ePVRTPF_DXT1 = 7,
 	ePVRTPF_DXT2,
 	ePVRTPF_DXT2,
 	ePVRTPF_DXT3,
 	ePVRTPF_DXT3,
 	ePVRTPF_DXT4,
 	ePVRTPF_DXT4,
 	ePVRTPF_DXT5,
 	ePVRTPF_DXT5,
-	ePVRTF_UNKNOWN_FORMAT = 0x7F
+	ePVRTPF_BC4,
+	ePVRTPF_BC5,
+	ePVRTPF_BC6,
+	ePVRTPF_BC7,
+	ePVRTPF_ETC2_RGB = 22,
+	ePVRTPF_ETC2_RGBA,
+	ePVRTPF_ETC2_RGBA1,
+	ePVRTPF_EAC_R = 25,
+	ePVRTPF_EAC_RG,
+	ePVRTPF_ASTC_4x4 = 27,
+	ePVRTPF_ASTC_5x4,
+	ePVRTPF_ASTC_5x5,
+	ePVRTPF_ASTC_6x5,
+	ePVRTPF_ASTC_6x6,
+	ePVRTPF_ASTC_8x5,
+	ePVRTPF_ASTC_8x6,
+	ePVRTPF_ASTC_8x8,
+	ePVRTPF_ASTC_10x5,
+	ePVRTPF_ASTC_10x6,
+	ePVRTPF_ASTC_10x8,
+	ePVRTPF_ASTC_10x10,
+	ePVRTPF_ASTC_12x10,
+	ePVRTPF_ASTC_12x12,
+	ePVRTPF_UNKNOWN_FORMAT = 0x7F
+};
+
+enum PVRV3ChannelType
+{
+	ePVRTCT_UNORM8 = 0,
+	ePVRTCT_SNORM8,
+	ePVRTCT_UINT8,
+	ePVRTCT_SINT8,
+	ePVRTCT_UNORM16,
+	ePVRTCT_SNORM16,
+	ePVRTCT_UINT16,
+	ePVRTCT_SINT16,
+	ePVRTCT_UNORM32,
+	ePVRTCT_SNORM32,
+	ePVRTCT_UINT32,
+	ePVRTCT_SINT32,
+	ePVRTCT_FLOAT
 };
 };
 
 
 // 'P' 'V' 'R' '!'
 // 'P' 'V' 'R' '!'
@@ -158,13 +198,26 @@ void ConvertPVRHeader(PVRTexHeaderV2 header2, PVRTexHeaderV3 *header3)
 		header3->pixelFormat = ePVRTPF_ETC1;
 		header3->pixelFormat = ePVRTPF_ETC1;
 		break;
 		break;
 	default:
 	default:
-		header3->pixelFormat = ePVRTF_UNKNOWN_FORMAT;
+		header3->pixelFormat = ePVRTPF_UNKNOWN_FORMAT;
 		break;
 		break;
 	}
 	}
 }
 }
 
 
-static CompressedImageData::Format convertFormat(PVRV3PixelFormat format)
+static CompressedImageData::Format convertFormat(PVRV3PixelFormat format, PVRV3ChannelType channeltype)
 {
 {
+	bool snorm = false;
+
+	switch (channeltype)
+	{
+	case ePVRTCT_SNORM8:
+	case ePVRTCT_SNORM16:
+	case ePVRTCT_SNORM32:
+		snorm = true;
+		break;
+	default:
+		break;
+	}
+
 	switch (format)
 	switch (format)
 	{
 	{
 	case ePVRTPF_PVRTCI_2bpp_RGB:
 	case ePVRTPF_PVRTCI_2bpp_RGB:
@@ -183,6 +236,39 @@ static CompressedImageData::Format convertFormat(PVRV3PixelFormat format)
 		return CompressedImageData::FORMAT_DXT3;
 		return CompressedImageData::FORMAT_DXT3;
 	case ePVRTPF_DXT5:
 	case ePVRTPF_DXT5:
 		return CompressedImageData::FORMAT_DXT5;
 		return CompressedImageData::FORMAT_DXT5;
+	case ePVRTPF_BC4:
+		if (snorm)
+			return CompressedImageData::FORMAT_BC4s;
+		else
+			return CompressedImageData::FORMAT_BC4;
+	case ePVRTPF_BC5:
+		if (snorm)
+			return CompressedImageData::FORMAT_BC5s;
+		else
+			return CompressedImageData::FORMAT_BC5;
+	case ePVRTPF_BC6:
+		if (snorm)
+			return CompressedImageData::FORMAT_BC6Hs;
+		else
+			return CompressedImageData::FORMAT_BC6H;
+	case ePVRTPF_BC7:
+		return CompressedImageData::FORMAT_BC7;
+	case ePVRTPF_ETC2_RGB:
+		return CompressedImageData::FORMAT_ETC2_RGB;
+	case ePVRTPF_ETC2_RGBA:
+		return CompressedImageData::FORMAT_ETC2_RGBA;
+	case ePVRTPF_ETC2_RGBA1:
+		return CompressedImageData::FORMAT_ETC2_RGBA1;
+	case ePVRTPF_EAC_R:
+		if (snorm)
+			return CompressedImageData::FORMAT_EAC_Rs;
+		else
+			return CompressedImageData::FORMAT_EAC_R;
+	case ePVRTPF_EAC_RG:
+		if (snorm)
+			return CompressedImageData::FORMAT_EAC_RGs;
+		else
+			return CompressedImageData::FORMAT_EAC_RG;
 	default:
 	default:
 		return CompressedImageData::FORMAT_UNKNOWN;
 		return CompressedImageData::FORMAT_UNKNOWN;
 	}
 	}
@@ -208,11 +294,20 @@ int getBitsPerPixel(uint64 pixelformat)
 	case ePVRTPF_PVRTCII_4bpp:
 	case ePVRTPF_PVRTCII_4bpp:
 	case ePVRTPF_ETC1:
 	case ePVRTPF_ETC1:
 	case ePVRTPF_DXT1:
 	case ePVRTPF_DXT1:
+	case ePVRTPF_BC4:
+	case ePVRTPF_ETC2_RGB:
+	case ePVRTPF_ETC2_RGBA1:
+	case ePVRTPF_EAC_R:
 		return 4;
 		return 4;
 	case ePVRTPF_DXT2:
 	case ePVRTPF_DXT2:
 	case ePVRTPF_DXT3:
 	case ePVRTPF_DXT3:
 	case ePVRTPF_DXT4:
 	case ePVRTPF_DXT4:
 	case ePVRTPF_DXT5:
 	case ePVRTPF_DXT5:
+	case ePVRTPF_BC5:
+	case ePVRTPF_BC6:
+	case ePVRTPF_BC7:
+	case ePVRTPF_ETC2_RGBA:
+	case ePVRTPF_EAC_RG:
 		return 8;
 		return 8;
 	default:
 	default:
 		return 0;
 		return 0;
@@ -244,7 +339,16 @@ void getFormatMinDimensions(uint64 pixelformat, int &minX, int &minY)
 	case ePVRTPF_DXT3:
 	case ePVRTPF_DXT3:
 	case ePVRTPF_DXT4:
 	case ePVRTPF_DXT4:
 	case ePVRTPF_DXT5:
 	case ePVRTPF_DXT5:
+	case ePVRTPF_BC4:
+	case ePVRTPF_BC5:
+	case ePVRTPF_BC6:
+	case ePVRTPF_BC7:
 	case ePVRTPF_ETC1:
 	case ePVRTPF_ETC1:
+	case ePVRTPF_ETC2_RGB:
+	case ePVRTPF_ETC2_RGBA:
+	case ePVRTPF_ETC2_RGBA1:
+	case ePVRTPF_EAC_R:
+	case ePVRTPF_EAC_RG:
 		minX = minY = 4;
 		minX = minY = 4;
 		break;
 		break;
 	default: // We don't handle all possible formats, but that's fine.
 	default: // We don't handle all possible formats, but that's fine.
@@ -324,7 +428,10 @@ uint8 *PVRHandler::parse(filesystem::FileData *filedata, std::vector<CompressedI
 	if (header3.depth > 1)
 	if (header3.depth > 1)
 		throw love::Exception("Image depths greater than 1 in PVR files are unsupported.");
 		throw love::Exception("Image depths greater than 1 in PVR files are unsupported.");
 
 
-	CompressedImageData::Format cformat = convertFormat((PVRV3PixelFormat) header3.pixelFormat);
+	PVRV3PixelFormat pixelformat = (PVRV3PixelFormat) header3.pixelFormat;
+	PVRV3ChannelType channeltype = (PVRV3ChannelType) header3.channelType;
+
+	CompressedImageData::Format cformat = convertFormat(pixelformat, channeltype);
 
 
 	if (cformat == CompressedImageData::FORMAT_UNKNOWN)
 	if (cformat == CompressedImageData::FORMAT_UNKNOWN)
 		throw love::Exception("Could not parse PVR file: unsupported image format.");
 		throw love::Exception("Could not parse PVR file: unsupported image format.");