1. rude
  2. love

Commits

Alex Szpakowski  committed 1d311d7

Removed support for BC7-compressed DDS images (only *very* modern systems support it right now); updated the ddsparse library

  • Participants
  • Parent commits ad55f6c
  • Branches default

Comments (0)

Files changed (10)

File src/libraries/ddsparse/ddsparse.cpp

View file
 using namespace dds::dxinfo;
 
 // Creates a packed uint representation of a FourCC code.
-static inline uint32_t FourCC(char a, char b, char c, char d)
+#define MakeFourCC(a, b, c, d) ((uint32_t) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)))
+
+// Translate the old DDS format to our own.
+static Format parseDDSFormat(const DDSPixelFormat &fmt)
 {
-	uint32_t fcc = ((uint32_t) a)
-	            | (((uint32_t) b) << 8)
-	            | (((uint32_t) c) << 16)
-	            | (((uint32_t) d) << 24);
+	if ((fmt.flags & DDPF_FOURCC) == 0)
+		return FORMAT_UNKNOWN;
 
-	return fcc;
+	Format f = FORMAT_UNKNOWN;
+
+	switch (fmt.fourCC)
+	{
+	case MakeFourCC('D','X','T','1'):
+		f = FORMAT_DXT1;
+		break;
+	case MakeFourCC('D','X','T','3'):
+		f = FORMAT_DXT3;
+		break;
+	case MakeFourCC('D','X','T','5'):
+		f = FORMAT_DXT5;
+		break;
+	case MakeFourCC('A','T','I','1'):
+	case MakeFourCC('B','C','4','U'):
+		f = FORMAT_BC4;
+		break;
+	case MakeFourCC('B','C','4','S'):
+		f = FORMAT_BC4s;
+		break;
+	case MakeFourCC('A','T','I','2'):
+	case MakeFourCC('B','C','5','U'):
+		f = FORMAT_BC5;
+		break;
+	case MakeFourCC('B','C','5','S'):
+		f = FORMAT_BC5s;
+		break;
+	default:
+		break;
+	}
+
+	return f;
 }
 
-Parser::Image::Image()
-	: width(0)
-	, height(0)
-	, dataSize(0)
-	, data(0)
-{
-}
-
-bool Parser::isDDS(const void *data, size_t dataSize)
-{
-	const uint8_t *readData = (const uint8_t *) data;
-	ptrdiff_t offset = 0;
-
-	// Is the data large enough to hold the DDS header?
-	if(dataSize < sizeof(uint32_t) + sizeof(DDSHeader))
-		return false;
-
-	// All DDS files start with "DDS ".
-	if((*(uint32_t *) readData) != FourCC('D','D','S',' '))
-		return false;
-
-	offset += sizeof(uint32_t);
-
-	DDSHeader *header = (DDSHeader *) &readData[offset];
-
-
-	// Verify header to validate DDS data.
-	if (header->size != sizeof(DDSHeader) || header->format.size != sizeof(DDSPixelFormat))
-		return false;
-
-	offset += sizeof(DDSHeader);
-
-	// Check for DX10 extension.
-	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == FourCC('D','X','1','0')))
-	{
-		// Data must be big enough for both headers plus the magic value.
-		if (dataSize < (sizeof(uint32_t) + sizeof(DDSHeader) + sizeof(DDSHeader10)))
-			return false;
-	}
-
-	return true;
-}
-
-bool Parser::isCompressedDDS(const void *data, size_t dataSize)
-{
-	if (!isDDS(data, dataSize))
-		return false;
-
-	const uint8_t *readData = (const uint8_t *) data;
-	ptrdiff_t offset = sizeof(uint32_t);
-
-	DDSHeader *header = (DDSHeader *) &readData[offset];
-	offset += sizeof(DDSHeader);
-
-	// Check for DX10 extension.
-	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == FourCC('D','X','1','0')))
-	{
-		DDSHeader10 *header10 = (DDSHeader10 *) &readData[offset];
-		return parseDX10Format(header10->dxgiFormat) != FORMAT_UNKNOWN;
-	}
-
-	return parseDDSFormat(header->format) != FORMAT_UNKNOWN;
-}
-
-Parser::Parser(const void *data, size_t dataSize)
-	: format(FORMAT_UNKNOWN)
-{
-	parseData(data, dataSize);
-}
-
-Parser::Parser(const Parser &other)
-	: texData(other.texData)
-	, format(other.format)
-{
-}
-
-Parser::Parser()
-	: format(FORMAT_UNKNOWN)
-{
-}
-
-Parser &Parser::operator = (const Parser &other)
-{
-	texData = other.texData;
-	format = other.format;
-
-	return *this;
-}
-
-Parser::~Parser()
-{
-}
-
-Format Parser::getFormat() const
-{
-	return format;
-}
-
-const Parser::Image *Parser::getImageData(size_t miplevel) const
-{
-	if (miplevel >= texData.size())
-		return 0;
-
-	return &texData[miplevel];
-}
-
-size_t Parser::getNumMipmaps() const
-{
-	return texData.size();
-}
-
-Format Parser::parseDDSFormat(const DDSPixelFormat &fmt)
-{
-	if (fmt.flags & DDPF_FOURCC)
-	{
-		if (fmt.fourCC == FourCC('D','X','T','1'))
-			return FORMAT_DXT1;
-		else if (fmt.fourCC == FourCC('D','X','T','3'))
-			return FORMAT_DXT3;
-		else if (fmt.fourCC == FourCC('D','X','T','5'))
-			return FORMAT_DXT5;
-		else if (fmt.fourCC == FourCC('A','T','I','1'))
-			return FORMAT_BC4;
-		else if (fmt.fourCC == FourCC('A','T','I','2'))
-			return FORMAT_BC5;
-		else if (fmt.fourCC == FourCC('B','C','4','U'))
-			return FORMAT_BC4;
-		else if (fmt.fourCC == FourCC('B','C','4','S'))
-			return FORMAT_BC4s;
-		else if (fmt.fourCC == FourCC('B','C','5','U'))
-			return FORMAT_BC5;
-		else if (fmt.fourCC == FourCC('B','C','5','S'))
-			return FORMAT_BC5s;
-	}
-
-	return FORMAT_UNKNOWN;
-}
-
-Format Parser::parseDX10Format(DXGIFormat fmt)
+// Translate the new DX10 formats to our own.
+static Format parseDX10Format(DXGIFormat fmt)
 {
 	Format f = FORMAT_UNKNOWN;
 
 	default:
 		break;
 	}
+	
+	return f;
+}
 
-	return f;
+bool isDDS(const void *data, size_t dataSize)
+{
+	const uint8_t *readData = (const uint8_t *) data;
+	ptrdiff_t offset = 0;
+
+	// Is the data large enough to hold the DDS header?
+	if(dataSize < sizeof(uint32_t) + sizeof(DDSHeader))
+		return false;
+
+	// All DDS files start with "DDS ".
+	if((*(uint32_t *) readData) != MakeFourCC('D','D','S',' '))
+		return false;
+
+	offset += sizeof(uint32_t);
+
+	DDSHeader *header = (DDSHeader *) &readData[offset];
+
+
+	// Verify header to validate DDS data.
+	if (header->size != sizeof(DDSHeader) || header->format.size != sizeof(DDSPixelFormat))
+		return false;
+
+	offset += sizeof(DDSHeader);
+
+	// Check for DX10 extension.
+	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == MakeFourCC('D','X','1','0')))
+	{
+		// Data must be big enough for both headers plus the magic value.
+		if (dataSize < (sizeof(uint32_t) + sizeof(DDSHeader) + sizeof(DDSHeader10)))
+			return false;
+	}
+
+	return true;
+}
+
+bool isCompressedDDS(const void *data, size_t dataSize)
+{
+	if (!isDDS(data, dataSize))
+		return false;
+
+	const uint8_t *readData = (const uint8_t *) data;
+	ptrdiff_t offset = sizeof(uint32_t);
+
+	DDSHeader *header = (DDSHeader *) &readData[offset];
+	offset += sizeof(DDSHeader);
+
+	// Check for DX10 extension.
+	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == MakeFourCC('D','X','1','0')))
+	{
+		DDSHeader10 *header10 = (DDSHeader10 *) &readData[offset];
+		return parseDX10Format(header10->dxgiFormat) != FORMAT_UNKNOWN;
+	}
+
+	return parseDDSFormat(header->format) != FORMAT_UNKNOWN;
+}
+
+Parser::Parser(const void *data, size_t dataSize)
+	: format(FORMAT_UNKNOWN)
+{
+	parseData(data, dataSize);
+}
+
+Parser::Parser(const Parser &other)
+	: texData(other.texData)
+	, format(other.format)
+{
+}
+
+Parser::Parser()
+	: format(FORMAT_UNKNOWN)
+{
+}
+
+Parser &Parser::operator = (const Parser &other)
+{
+	texData = other.texData;
+	format = other.format;
+
+	return *this;
+}
+
+Parser::~Parser()
+{
+}
+
+Format Parser::getFormat() const
+{
+	return format;
+}
+
+const Image *Parser::getImageData(size_t miplevel) const
+{
+	if (miplevel >= texData.size())
+		return 0;
+
+	return &texData[miplevel];
+}
+
+size_t Parser::getMipmapCount() const
+{
+	return texData.size();
 }
 
 size_t Parser::parseImageSize(Format fmt, int width, int height) const
 
 
 	// Check for DX10 extension.
-	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == FourCC('D','X','1','0')))
+	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == MakeFourCC('D','X','1','0')))
 	{
 		DDSHeader10 *header10 = (DDSHeader10 *) &readData[offset];
 		offset += sizeof(DDSHeader10);

File src/libraries/ddsparse/ddsparse.h

View file
 #ifndef DDS_PARSE_H
 #define DDS_PARSE_H
 
-#include "ddsinfo.h"
-
 #include <stddef.h>
 #include <stdint.h>
 
 #include <vector>
-#include <exception>
 
 namespace dds
 {
 	FORMAT_UNKNOWN
 };
 
+// Represents a single mipmap level of a texture.
+struct Image
+{
+	int width;
+	int height;
+	size_t dataSize;
+	const uint8_t *data;
+
+	Image() : width(0), height(0), dataSize(0), data(0)
+	{};
+};
+
+/**
+ * Determines whether the input byte data represents a valid DDS file.
+ * Does not take into account whether the texture format is supported.
+ *
+ * @param data     The byte data to parse.
+ * @param dataSize The size in bytes of the data.
+ **/
+bool isDDS(const void *data, size_t dataSize);
+
+/**
+ * Determines whether the input byte data represents a valid compressed DDS
+ * file. Takes into account texture format, but not type (3D textures, etc.)
+ *
+ * @param data     The byte data to parse.
+ * @param dataSize The size in bytes of the data.
+ **/
+bool isCompressedDDS(const void *data, size_t dataSize);
+
 class Parser
 {
 public:
 
-	// Represents a single mipmap level of a texture.
-	struct Image
-	{
-		int width;
-		int height;
-		size_t dataSize;
-		const uint8_t *data;
-
-		Image();
-	};
-
-	/**
-	 * Determines whether the input byte data represents a valid DDS file.
-	 * Does not take into account whether the texture format is supported.
-	 *
-	 * @param data     The byte data to parse.
-	 * @param dataSize The size in bytes of the data.
-	 **/
-	static bool isDDS(const void *data, size_t dataSize);
-
-	/**
-	 * Determines whether the input byte data represents a valid compressed DDS
-	 * file. Takes into account texture format, but not type (3D textures, etc.)
-	 *
-	 * @param data     The byte data to parse.
-	 * @param dataSize The size in bytes of the data.
-	 **/
-	static bool isCompressedDDS(const void *data, size_t dataSize);
-
 	/**
 	 * Constructor.
 	 * Attempts to parse byte data as a compressed DDS file.
 	 * Gets the number of mipmap levels in this texture.
 	 * Includes the base mip level.
 	 **/
-	size_t getNumMipmaps() const;
+	size_t getMipmapCount() const;
 
 private:
 
-	static Format parseDDSFormat(const dxinfo::DDSPixelFormat &fmt);
-	static Format parseDX10Format(dxinfo::DXGIFormat fmt);
-
 	size_t parseImageSize(Format fmt, int width, int height) const;
-
 	bool parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int w, int h, int mips);
-
 	bool parseData(const void *data, size_t dataSize);
 
 	std::vector<Image> texData;

File src/modules/graphics/Graphics.cpp

View file
 	{ "mipmap", Graphics::SUPPORT_MIPMAP },
 	{ "dxt", Graphics::SUPPORT_DXT },
 	{ "bc5", Graphics::SUPPORT_BC5 },
-	{ "bc7", Graphics::SUPPORT_BC7 },
 };
 
 StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM> Graphics::support(Graphics::supportEntries, sizeof(Graphics::supportEntries));

File src/modules/graphics/Graphics.h

View file
 		SUPPORT_MIPMAP,
 		SUPPORT_DXT,
 		SUPPORT_BC5,
-		SUPPORT_BC7,
 		SUPPORT_MAX_ENUM
 	};
 

File src/modules/graphics/opengl/Image.cpp

View file
 		return GL_COMPRESSED_RG_RGTC2;
 	case image::CompressedData::TYPE_BC5s:
 		return GL_COMPRESSED_SIGNED_RG_RGTC2;
-	case image::CompressedData::TYPE_BC7:
-		return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
-	case image::CompressedData::TYPE_BC7srgb:
-		return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
 	default:
 		return GL_RGBA8;
 	}
 	case image::CompressedData::TYPE_DXT3:
 	case image::CompressedData::TYPE_DXT5:
 		return GLEE_EXT_texture_compression_s3tc;
-
 	case image::CompressedData::TYPE_BC5:
 	case image::CompressedData::TYPE_BC5s:
 		return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc);
-
-	case image::CompressedData::TYPE_BC7:
-	case image::CompressedData::TYPE_BC7srgb:
-		return (GLEE_VERSION_4_2 || GLEE_ARB_texture_compression_bptc);
-
 	default:
 		return false;
 

File src/modules/graphics/opengl/wrap_Graphics.cpp

View file
 			if (!Image::hasCompressedTextureSupport(image::CompressedData::TYPE_BC5))
 				supported = false;
 			break;
-		case Graphics::SUPPORT_BC7:
-			if (!Image::hasCompressedTextureSupport(image::CompressedData::TYPE_BC7))
-				supported = false;
-			break;
 		default:
 			supported = false;
 		}

File src/modules/image/CompressedData.cpp

View file
 	{"dxt5", CompressedData::TYPE_DXT5},
 	{"bc5", CompressedData::TYPE_BC5},
 	{"bc5s", CompressedData::TYPE_BC5s},
-	{"bc7", CompressedData::TYPE_BC7},
-	{"bc7srgb", CompressedData::TYPE_BC7srgb},
 };
 
 StringMap<CompressedData::TextureType, CompressedData::TYPE_MAX_ENUM> CompressedData::types(CompressedData::typeEntries, sizeof(CompressedData::typeEntries));

File src/modules/image/CompressedData.h

View file
 namespace image
 {
 
-// CompressedData represents image data which is designed to be uploaded to the
-// GPU and rendered in its compressed form, without being un-compressed.
-// http://renderingpipeline.com/2012/07/texture-compression/
-
+/**
+ * CompressedData represents image data which is designed to be uploaded to the
+ * GPU and rendered in its compressed form, without being un-compressed.
+ * http://renderingpipeline.com/2012/07/texture-compression/
+ **/
 class CompressedData : public Data
 {
 public:
 		TYPE_DXT5,
 		TYPE_BC5,
 		TYPE_BC5s,
-		TYPE_BC7,
-		TYPE_BC7srgb,
 		TYPE_MAX_ENUM
 	};
 

File src/modules/image/magpie/ddsHandler.cpp

View file
 	if (data->getExtension().compare("dds") != 0)
 		return false;
 
-	return dds::Parser::isCompressedDDS(data->getData(), data->getSize());
+	return dds::isCompressedDDS(data->getData(), data->getSize());
 }
 
 CompressedData::TextureType ddsHandler::parse(filesystem::FileData *data, std::vector<CompressedData::SubImage> &images)
 {
-	if (!dds::Parser::isDDS(data->getData(), data->getSize()))
+	if (!dds::isDDS(data->getData(), data->getSize()))
 		throw love::Exception("Could not decode compressed data (not a DDS file?)");
 
 	CompressedData::TextureType textype = CompressedData::TYPE_UNKNOWN;
 		if (textype == CompressedData::TYPE_UNKNOWN)
 			throw love::Exception("Could not parse compressed data: Unsupported format.");
 
-		if (parser.getNumMipmaps() == 0)
+		if (parser.getMipmapCount() == 0)
 			throw love::Exception("Could not parse compressed data: No readable texture data.");
 
-		for (size_t i = 0; i < parser.getNumMipmaps(); i++)
+		for (size_t i = 0; i < parser.getMipmapCount(); i++)
 		{
-			const dds::Parser::Image *img = parser.getImageData(i);
+			const dds::Image *img = parser.getImageData(i);
 
 			CompressedData::SubImage mip;
 
 		return CompressedData::TYPE_BC5;
 	case dds::FORMAT_BC5s:
 		return CompressedData::TYPE_BC5s;
-	case dds::FORMAT_BC7:
-		return CompressedData::TYPE_BC7;
-	case dds::FORMAT_BC7srgb:
-		return CompressedData::TYPE_BC7srgb;
 	default:
 		return CompressedData::TYPE_UNKNOWN;
 	}

File src/modules/image/magpie/ddsHandler.h

View file
 #define LOVE_IMAGE_MAGPIE_DDS_HANDLER_H
 
 // LOVE
+#include "common/EnumMap.h"
 #include "filesystem/FileData.h"
 #include "image/CompressedData.h"