mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Add support for loading DDS files that contain raw/uncompressed pixel data. Resolves issue #1097.
This commit is contained in:
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "ddsHandler.h"
|
||||
#include "common/Exception.h"
|
||||
#include "image/ImageData.h"
|
||||
|
||||
// dds parser
|
||||
#include "ddsparse/ddsparse.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -28,6 +32,172 @@ namespace image
|
||||
namespace magpie
|
||||
{
|
||||
|
||||
static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB)
|
||||
{
|
||||
using namespace dds::dxinfo;
|
||||
|
||||
sRGB = false;
|
||||
|
||||
switch (dxformat)
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
return PIXELFORMAT_RGBA32F;
|
||||
|
||||
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
return PIXELFORMAT_RGBA16F;
|
||||
|
||||
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
||||
return PIXELFORMAT_RGBA16;
|
||||
|
||||
case DXGI_FORMAT_R32G32_TYPELESS:
|
||||
case DXGI_FORMAT_R32G32_FLOAT:
|
||||
return PIXELFORMAT_RG32F;
|
||||
|
||||
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
return PIXELFORMAT_RGB10A2;
|
||||
|
||||
case DXGI_FORMAT_R11G11B10_FLOAT:
|
||||
return PIXELFORMAT_RG11B10F;
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
|
||||
return PIXELFORMAT_RGBA8;
|
||||
|
||||
case DXGI_FORMAT_R16G16_TYPELESS:
|
||||
case DXGI_FORMAT_R16G16_FLOAT:
|
||||
return PIXELFORMAT_RG16F;
|
||||
|
||||
case DXGI_FORMAT_R16G16_UNORM:
|
||||
return PIXELFORMAT_RG16;
|
||||
|
||||
case DXGI_FORMAT_R32_TYPELESS:
|
||||
case DXGI_FORMAT_R32_FLOAT:
|
||||
return PIXELFORMAT_R32F;
|
||||
|
||||
case DXGI_FORMAT_R8G8_TYPELESS:
|
||||
case DXGI_FORMAT_R8G8_UNORM:
|
||||
return PIXELFORMAT_RG8;
|
||||
|
||||
case DXGI_FORMAT_R16_TYPELESS:
|
||||
case DXGI_FORMAT_R16_FLOAT:
|
||||
return PIXELFORMAT_R16F;
|
||||
|
||||
case DXGI_FORMAT_R16_UNORM:
|
||||
return PIXELFORMAT_R16;
|
||||
|
||||
case DXGI_FORMAT_R8_TYPELESS:
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
case DXGI_FORMAT_A8_UNORM:
|
||||
return PIXELFORMAT_R8;
|
||||
|
||||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC1_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT1;
|
||||
|
||||
case DXGI_FORMAT_BC2_TYPELESS:
|
||||
case DXGI_FORMAT_BC2_UNORM:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC2_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT3;
|
||||
|
||||
case DXGI_FORMAT_BC3_TYPELESS:
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC3_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT5;
|
||||
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
return PIXELFORMAT_BC4;
|
||||
|
||||
case DXGI_FORMAT_BC4_SNORM:
|
||||
return PIXELFORMAT_BC4s;
|
||||
|
||||
case DXGI_FORMAT_BC5_TYPELESS:
|
||||
case DXGI_FORMAT_BC5_UNORM:
|
||||
return PIXELFORMAT_BC5;
|
||||
|
||||
case DXGI_FORMAT_BC5_SNORM:
|
||||
return PIXELFORMAT_BC5s;
|
||||
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
return PIXELFORMAT_RGB565;
|
||||
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
return PIXELFORMAT_RGB5A1;
|
||||
|
||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||
case DXGI_FORMAT_BC6H_UF16:
|
||||
return PIXELFORMAT_BC6H;
|
||||
|
||||
case DXGI_FORMAT_BC6H_SF16:
|
||||
return PIXELFORMAT_BC6Hs;
|
||||
|
||||
case DXGI_FORMAT_BC7_TYPELESS:
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC7_UNORM_SRGB);
|
||||
return PIXELFORMAT_BC7;
|
||||
|
||||
default:
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
bool DDSHandler::canDecode(Data *data)
|
||||
{
|
||||
using namespace dds::dxinfo;
|
||||
|
||||
DXGIFormat dxformat = dds::getDDSPixelFormat(data->getData(), data->getSize());
|
||||
bool isSRGB = false;
|
||||
PixelFormat format = convertFormat(dxformat, isSRGB);
|
||||
|
||||
return ImageData::validPixelFormat(format);
|
||||
}
|
||||
|
||||
FormatHandler::DecodedImage DDSHandler::decode(Data *data)
|
||||
{
|
||||
DecodedImage img;
|
||||
|
||||
dds::Parser parser(data->getData(), data->getSize());
|
||||
|
||||
bool isSRGB = false;
|
||||
img.format = convertFormat(parser.getFormat(), isSRGB);
|
||||
|
||||
if (!ImageData::validPixelFormat(img.format))
|
||||
throw love::Exception("Could not parse DDS pixel data: Unsupported format.");
|
||||
|
||||
if (parser.getMipmapCount() == 0)
|
||||
throw love::Exception("Could not parse DDS pixel data: No readable texture data.");
|
||||
|
||||
// We only support the top mip level through this codepath.
|
||||
const dds::Image *ddsimg = parser.getImageData(0);
|
||||
|
||||
try
|
||||
{
|
||||
img.data = new uint8[ddsimg->dataSize];
|
||||
}
|
||||
catch (std::exception &)
|
||||
{
|
||||
throw love::Exception("Out of memory.");
|
||||
}
|
||||
|
||||
memcpy(img.data, ddsimg->data, ddsimg->dataSize);
|
||||
|
||||
img.size = ddsimg->dataSize;
|
||||
img.width = ddsimg->width;
|
||||
img.height = ddsimg->height;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
bool DDSHandler::canParseCompressed(Data *data)
|
||||
{
|
||||
return dds::isCompressedDDS(data->getData(), data->getSize());
|
||||
@@ -35,7 +205,7 @@ bool DDSHandler::canParseCompressed(Data *data)
|
||||
|
||||
StrongRef<CompressedMemory> DDSHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
{
|
||||
if (!dds::isDDS(filedata->getData(), filedata->getSize()))
|
||||
if (!dds::isCompressedDDS(filedata->getData(), filedata->getSize()))
|
||||
throw love::Exception("Could not decode compressed data (not a DDS file?)");
|
||||
|
||||
PixelFormat texformat = PIXELFORMAT_UNKNOWN;
|
||||
@@ -88,49 +258,6 @@ StrongRef<CompressedMemory> DDSHandler::parseCompressed(Data *filedata, std::vec
|
||||
return memory;
|
||||
}
|
||||
|
||||
PixelFormat DDSHandler::convertFormat(dds::Format ddsformat, bool &sRGB)
|
||||
{
|
||||
sRGB = false;
|
||||
|
||||
switch (ddsformat)
|
||||
{
|
||||
case dds::FORMAT_DXT1:
|
||||
return PIXELFORMAT_DXT1;
|
||||
case dds::FORMAT_DXT1srgb:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT1;
|
||||
case dds::FORMAT_DXT3:
|
||||
return PIXELFORMAT_DXT3;
|
||||
case dds::FORMAT_DXT3srgb:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT3;
|
||||
case dds::FORMAT_DXT5:
|
||||
return PIXELFORMAT_DXT5;
|
||||
case dds::FORMAT_DXT5srgb:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT5;
|
||||
case dds::FORMAT_BC4:
|
||||
return PIXELFORMAT_BC4;
|
||||
case dds::FORMAT_BC4s:
|
||||
return PIXELFORMAT_BC4s;
|
||||
case dds::FORMAT_BC5:
|
||||
return PIXELFORMAT_BC5;
|
||||
case dds::FORMAT_BC5s:
|
||||
return PIXELFORMAT_BC5s;
|
||||
case dds::FORMAT_BC6H:
|
||||
return PIXELFORMAT_BC6H;
|
||||
case dds::FORMAT_BC6Hs:
|
||||
return PIXELFORMAT_BC6Hs;
|
||||
case dds::FORMAT_BC7:
|
||||
return PIXELFORMAT_BC7;
|
||||
case dds::FORMAT_BC7srgb:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_BC7;
|
||||
default:
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
} // magpie
|
||||
} // image
|
||||
} // love
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
// LOVE
|
||||
#include "image/FormatHandler.h"
|
||||
|
||||
// dds parser
|
||||
#include "ddsparse/ddsparse.h"
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
|
||||
@@ -46,16 +43,13 @@ public:
|
||||
virtual ~DDSHandler() {}
|
||||
|
||||
// Implements FormatHandler.
|
||||
bool canDecode(Data *data) override;
|
||||
DecodedImage decode(Data *data) override;
|
||||
bool canParseCompressed(Data *data) override;
|
||||
|
||||
StrongRef<CompressedMemory> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
|
||||
private:
|
||||
|
||||
static PixelFormat convertFormat(dds::Format ddsformat, bool &sRGB);
|
||||
|
||||
}; // DDSHandler
|
||||
|
||||
} // magpie
|
||||
|
||||
Reference in New Issue
Block a user