Browse Source

Improved the performance of dds data loading (love.image.newCompressedData / love.graphics.newImage("myfile.dds"))

Alex Szpakowski 12 years ago
parent
commit
03f5bd9a5a

+ 1 - 1
src/modules/image/CompressedData.cpp

@@ -50,7 +50,7 @@ void *CompressedData::getData() const
 	// Data for different mipmap levels is not stored contiguously in memory, so
 	// Data for different mipmap levels is not stored contiguously in memory, so
 	// getData() won't work properly for CompressedData.
 	// getData() won't work properly for CompressedData.
 	if (dataImages.size() > 0 && dataImages[0].size > 0)
 	if (dataImages.size() > 0 && dataImages[0].size > 0)
-		return (void *) &(dataImages[0].data[0]);
+		return (void *) dataImages[0].data;
 	else
 	else
 		return 0;
 		return 0;
 }
 }

+ 1 - 1
src/modules/image/CompressedData.h

@@ -63,7 +63,7 @@ public:
 	{
 	{
 		int width, height;
 		int width, height;
 		size_t size;
 		size_t size;
-		std::vector<unsigned char> data;
+		char *data;
 	};
 	};
 
 
 	CompressedData();
 	CompressedData();

+ 10 - 0
src/modules/image/magpie/CompressedData.cpp

@@ -36,6 +36,9 @@ CompressedData::CompressedData(love::filesystem::FileData *data)
 
 
 CompressedData::~CompressedData()
 CompressedData::~CompressedData()
 {
 {
+	// We have ownership of the heap memory in dataImages, so we have to free it.
+	for (size_t i = 0; i < dataImages.size(); i++)
+		delete[] dataImages[i].data;
 }
 }
 
 
 void CompressedData::load(love::filesystem::FileData *data)
 void CompressedData::load(love::filesystem::FileData *data)
@@ -53,6 +56,13 @@ void CompressedData::load(love::filesystem::FileData *data)
 	if (parsedimages.size() == 0)
 	if (parsedimages.size() == 0)
 		throw love::Exception("Could not parse compressed data: No valid data?");
 		throw love::Exception("Could not parse compressed data: No valid data?");
 
 
+	// Make sure to clean up any previously loaded data.
+	for (size_t i = 0; i < dataImages.size(); i++)
+	{
+		delete[] dataImages[i].data;
+		dataImages[i].data = 0;
+	}
+
 	dataImages = parsedimages;
 	dataImages = parsedimages;
 	type = textype;
 	type = textype;
 }
 }

+ 7 - 1
src/modules/image/magpie/DevilHandler.cpp

@@ -54,6 +54,11 @@ void DevilHandler::init()
 void DevilHandler::quit()
 void DevilHandler::quit()
 {
 {
 	ilShutDown();
 	ilShutDown();
+	if (devilMutex)
+	{
+		delete devilMutex;
+		devilMutex = 0;
+	}
 }
 }
 
 
 bool DevilHandler::canDecode(love::filesystem::FileData * /*data*/)
 bool DevilHandler::canDecode(love::filesystem::FileData * /*data*/)
@@ -210,9 +215,10 @@ DevilHandler::EncodedImage DevilHandler::encode(const DecodedImage &img, ImageDa
 	}
 	}
 	catch (std::exception &e)
 	catch (std::exception &e)
 	{
 	{
-		// catches love and std exceptions
+		// Catches love and std exceptions.
 		ilDeleteImage(tempimage);
 		ilDeleteImage(tempimage);
 		delete[] encodedimage.data;
 		delete[] encodedimage.data;
+		encodedimage.data = 0;
 		throw love::Exception("%s", e.what());
 		throw love::Exception("%s", e.what());
 	}
 	}
 
 

+ 11 - 1
src/modules/image/magpie/ddsHandler.cpp

@@ -44,6 +44,7 @@ CompressedData::TextureType ddsHandler::parse(filesystem::FileData *data, std::v
 
 
 	try
 	try
 	{
 	{
+		// Attempt to parse the dds file.
 		dds::Parser parser(data->getData(), data->getSize());
 		dds::Parser parser(data->getData(), data->getSize());
 
 
 		textype = convertFormat(parser.getFormat());
 		textype = convertFormat(parser.getFormat());
@@ -54,8 +55,10 @@ CompressedData::TextureType ddsHandler::parse(filesystem::FileData *data, std::v
 		if (parser.getMipmapCount() == 0)
 		if (parser.getMipmapCount() == 0)
 			throw love::Exception("Could not parse compressed data: No readable texture data.");
 			throw love::Exception("Could not parse compressed data: No readable texture data.");
 
 
+		// Copy the parsed mipmap levels from the FileData to our CompressedData.
 		for (size_t i = 0; i < parser.getMipmapCount(); i++)
 		for (size_t i = 0; i < parser.getMipmapCount(); i++)
 		{
 		{
+			// Fetch the data for this mipmap level.
 			const dds::Image *img = parser.getImageData(i);
 			const dds::Image *img = parser.getImageData(i);
 
 
 			CompressedData::SubImage mip;
 			CompressedData::SubImage mip;
@@ -63,13 +66,20 @@ CompressedData::TextureType ddsHandler::parse(filesystem::FileData *data, std::v
 			mip.width = img->width;
 			mip.width = img->width;
 			mip.height = img->height;
 			mip.height = img->height;
 			mip.size = img->dataSize;
 			mip.size = img->dataSize;
-			mip.data.insert(mip.data.begin(), &img->data[0], &img->data[mip.size]);
+
+			// Copy the mipmap image from the FileData.
+			mip.data = new char[mip.size];
+			memcpy(mip.data, img->data, mip.size);
 
 
 			images.push_back(mip);
 			images.push_back(mip);
 		}
 		}
 	}
 	}
 	catch (std::exception &e)
 	catch (std::exception &e)
 	{
 	{
+		// Clean up any newly allocated heap memory before throwing.
+		for (size_t i = 0; i < images.size(); i++)
+			delete[] images[i].data;
+
 		throw love::Exception(e.what());
 		throw love::Exception(e.what());
 	}
 	}