diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index 42325510f..ce8a3a690 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -364,11 +364,8 @@ PixelFormat getSRGBPixelFormat(PixelFormat format) case PIXELFORMAT_ASTC_10x10_UNORM: return PIXELFORMAT_ASTC_10x10_sRGB; case PIXELFORMAT_ASTC_12x10_UNORM: return PIXELFORMAT_ASTC_12x10_sRGB; case PIXELFORMAT_ASTC_12x12_UNORM: return PIXELFORMAT_ASTC_12x12_sRGB; - default: - break; + default: return format; } - - return format; } PixelFormat getLinearPixelFormat(PixelFormat format) @@ -398,11 +395,8 @@ PixelFormat getLinearPixelFormat(PixelFormat format) case PIXELFORMAT_ASTC_10x10_sRGB: return PIXELFORMAT_ASTC_10x10_UNORM; case PIXELFORMAT_ASTC_12x10_sRGB: return PIXELFORMAT_ASTC_12x10_UNORM; case PIXELFORMAT_ASTC_12x12_sRGB: return PIXELFORMAT_ASTC_12x12_UNORM; - default: - break; + default: return format; } - - return format; } size_t getPixelFormatBlockSize(PixelFormat format) diff --git a/src/modules/graphics/GraphicsReadback.cpp b/src/modules/graphics/GraphicsReadback.cpp index 935499ab5..0289bddf7 100644 --- a/src/modules/graphics/GraphicsReadback.cpp +++ b/src/modules/graphics/GraphicsReadback.cpp @@ -81,6 +81,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture } textureFormat = getLinearPixelFormat(texture->getPixelFormat()); + isFormatLinear = isGammaCorrect() && !isPixelFormatSRGB(texture->getPixelFormat()); if (!image::ImageData::validPixelFormat(textureFormat)) { @@ -96,7 +97,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture if (isRT && !caps.features[Graphics::FEATURE_COPY_RENDER_TARGET_TO_BUFFER]) throw love::Exception("readbackTextureAsync is not supported on this system."); else if (!isRT && !caps.features[Graphics::FEATURE_COPY_TEXTURE_TO_BUFFER]) - throw love::Exception("readbackTextureAsync a with non-render-target textures is not supported on this system."); + throw love::Exception("readbackTextureAsync with a non-render-target texture is not supported on this system."); } else { @@ -158,6 +159,7 @@ void *GraphicsReadback::prepareReadbackDest(size_t size) throw love::Exception("The love.image module must be loaded for readbackTexture."); imageData.set(module->newImageData(rect.w, rect.h, textureFormat, nullptr), Acquire::NORETAIN); + imageData->setLinear(isFormatLinear); return imageData->getData(); } } diff --git a/src/modules/graphics/GraphicsReadback.h b/src/modules/graphics/GraphicsReadback.h index 0524d4c2b..8990314d3 100644 --- a/src/modules/graphics/GraphicsReadback.h +++ b/src/modules/graphics/GraphicsReadback.h @@ -103,6 +103,7 @@ class GraphicsReadback : public love::Object StrongRef imageData; Rect rect = {}; PixelFormat textureFormat = PIXELFORMAT_UNKNOWN; + bool isFormatLinear = false; int imageDataX = 0; int imageDataY = 0; diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 4d0e59fcf..2071ce6f1 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -203,7 +203,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) love::image::ImageDataBase *slice = slices->get(0, 0); format = slice->getFormat(); - if (isGammaCorrect() && !settings.linear) + if (isGammaCorrect() && !slice->isLinear()) format = getSRGBPixelFormat(format); pixelWidth = slice->getWidth(); @@ -886,6 +886,7 @@ bool Texture::Slices::validate() const int w = firstdata->getWidth(); int h = firstdata->getHeight(); PixelFormat format = firstdata->getFormat(); + bool linear = firstdata->isLinear(); if (textureType == TEXTURE_CUBE && w != h) throw love::Exception("Cube textures must have equal widths and heights for each cube face."); @@ -925,6 +926,9 @@ bool Texture::Slices::validate() const if (format != slicedata->getFormat()) throw love::Exception("All texture slices and mipmaps must have the same pixel format."); + + if (linear != slicedata->isLinear()) + throw love::Exception("All texture slices and mipmaps must have the same linear setting."); } mipw = std::max(mipw / 2, 1); diff --git a/src/modules/image/CompressedImageData.cpp b/src/modules/image/CompressedImageData.cpp index 0ff04cb5d..724367a12 100644 --- a/src/modules/image/CompressedImageData.cpp +++ b/src/modules/image/CompressedImageData.cpp @@ -30,7 +30,6 @@ love::Type CompressedImageData::type("CompressedImageData", &Data::type); CompressedImageData::CompressedImageData(const std::list &formats, Data *filedata) : format(PIXELFORMAT_UNKNOWN) - , sRGB(false) { FormatHandler *parser = nullptr; @@ -46,7 +45,7 @@ CompressedImageData::CompressedImageData(const std::list &forma if (parser == nullptr) throw love::Exception("Could not parse compressed data: Unknown format."); - memory = parser->parseCompressed(filedata, dataImages, format, sRGB); + memory = parser->parseCompressed(filedata, dataImages, format); if (memory == nullptr) throw love::Exception("Could not parse compressed data."); @@ -56,11 +55,14 @@ CompressedImageData::CompressedImageData(const std::list &forma if (dataImages.size() == 0 || memory->getSize() == 0) throw love::Exception("Could not parse compressed data: No valid data?"); + + // This throws away some information the decoder could give us, but we + // can't really rely on it I think... + format = getLinearPixelFormat(format); } CompressedImageData::CompressedImageData(const CompressedImageData &c) : format(c.format) - , sRGB(c.sRGB) { memory.set(c.memory->clone(), Acquire::NORETAIN); @@ -134,9 +136,15 @@ PixelFormat CompressedImageData::getFormat() const return format; } -bool CompressedImageData::isSRGB() const +void CompressedImageData::setLinear(bool linear) +{ + for (auto &slice : dataImages) + slice->setLinear(linear); +} + +bool CompressedImageData::isLinear() const { - return sRGB; + return dataImages.empty() ? false : dataImages[0]->isLinear(); } CompressedSlice *CompressedImageData::getSlice(int slice, int miplevel) const diff --git a/src/modules/image/CompressedImageData.h b/src/modules/image/CompressedImageData.h index e834935b1..70e55cc19 100644 --- a/src/modules/image/CompressedImageData.h +++ b/src/modules/image/CompressedImageData.h @@ -93,14 +93,14 @@ class CompressedImageData : public Data **/ PixelFormat getFormat() const; - bool isSRGB() const; + void setLinear(bool linear); + bool isLinear() const; CompressedSlice *getSlice(int slice, int miplevel) const; protected: PixelFormat format; - bool sRGB; // Single block of memory containing all of the sub-images. StrongRef memory; diff --git a/src/modules/image/CompressedSlice.cpp b/src/modules/image/CompressedSlice.cpp index a4ab37d6f..f2116a1d9 100644 --- a/src/modules/image/CompressedSlice.cpp +++ b/src/modules/image/CompressedSlice.cpp @@ -31,7 +31,6 @@ CompressedSlice::CompressedSlice(PixelFormat format, int width, int height, Byte , memory(memory) , offset(offset) , dataSize(size) - , sRGB(false) { } @@ -40,7 +39,6 @@ CompressedSlice::CompressedSlice(const CompressedSlice &s) , memory(s.memory) , offset(s.offset) , dataSize(s.dataSize) - , sRGB(s.sRGB) { } diff --git a/src/modules/image/CompressedSlice.h b/src/modules/image/CompressedSlice.h index 581641b9c..09d009adc 100644 --- a/src/modules/image/CompressedSlice.h +++ b/src/modules/image/CompressedSlice.h @@ -46,7 +46,6 @@ class CompressedSlice : public ImageDataBase CompressedSlice *clone() const override; void *getData() const override { return (uint8 *) memory->getData() + offset; } size_t getSize() const override { return dataSize; } - bool isSRGB() const override { return sRGB; } size_t getOffset() const { return offset; } private: @@ -54,7 +53,6 @@ class CompressedSlice : public ImageDataBase StrongRef memory; size_t offset; size_t dataSize; - bool sRGB; }; // CompressedSlice diff --git a/src/modules/image/FormatHandler.cpp b/src/modules/image/FormatHandler.cpp index b75b9a226..692d38e70 100644 --- a/src/modules/image/FormatHandler.cpp +++ b/src/modules/image/FormatHandler.cpp @@ -60,7 +60,7 @@ bool FormatHandler::canParseCompressed(Data* /*data*/) return false; } -StrongRef FormatHandler::parseCompressed(Data* /*filedata*/, std::vector>& /*images*/, PixelFormat& /*format*/, bool& /*sRGB*/) +StrongRef FormatHandler::parseCompressed(Data* /*filedata*/, std::vector>& /*images*/, PixelFormat& /*format*/) { throw love::Exception("Compressed image parsing is not implemented for this format backend."); } diff --git a/src/modules/image/FormatHandler.h b/src/modules/image/FormatHandler.h index 9fc6cab16..762905f82 100644 --- a/src/modules/image/FormatHandler.h +++ b/src/modules/image/FormatHandler.h @@ -106,13 +106,12 @@ class FormatHandler : public love::Object * @param[out] images The list of sub-images generated. Byte data is a * pointer to the returned data. * @param[out] format The format of the Compressed Data. - * @param[out] sRGB Whether the texture is sRGB-encoded. * * @return The single block of memory containing the parsed images. **/ virtual StrongRef parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB); + PixelFormat &format); /** * Frees raw pixel memory allocated by the format handler. diff --git a/src/modules/image/ImageData.cpp b/src/modules/image/ImageData.cpp index 108a945ae..377569cc3 100644 --- a/src/modules/image/ImageData.cpp +++ b/src/modules/image/ImageData.cpp @@ -152,6 +152,10 @@ void ImageData::decode(Data *data) else delete[] this->data; + // This throws away some information the decoder could give us, but we + // can't really rely on it I think... + decodedimage.format = getLinearPixelFormat(decodedimage.format); + this->width = decodedimage.width; this->height = decodedimage.height; this->data = decodedimage.data; @@ -247,11 +251,6 @@ void *ImageData::getData() const return data; } -bool ImageData::isSRGB() const -{ - return false; -} - bool ImageData::inside(int x, int y) const { return x >= 0 && x < getWidth() && y >= 0 && y < getHeight(); diff --git a/src/modules/image/ImageData.h b/src/modules/image/ImageData.h index fa43a848c..c0fad8dba 100644 --- a/src/modules/image/ImageData.h +++ b/src/modules/image/ImageData.h @@ -62,7 +62,7 @@ class ImageData : public ImageDataBase static love::Type type; ImageData(Data *data); - ImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8_UNORM); + ImageData(int width, int height, PixelFormat format); ImageData(int width, int height, PixelFormat format, void *data, bool own); ImageData(const ImageData &c); virtual ~ImageData(); @@ -116,7 +116,6 @@ class ImageData : public ImageDataBase ImageData *clone() const override; void *getData() const override; size_t getSize() const override; - bool isSRGB() const override; size_t getPixelSize() const; diff --git a/src/modules/image/ImageDataBase.cpp b/src/modules/image/ImageDataBase.cpp index 1e7248c9c..56b698757 100644 --- a/src/modules/image/ImageDataBase.cpp +++ b/src/modules/image/ImageDataBase.cpp @@ -29,6 +29,7 @@ ImageDataBase::ImageDataBase(PixelFormat format, int width, int height) : format(format) , width(width) , height(height) + , linear(false) { } @@ -47,5 +48,15 @@ int ImageDataBase::getHeight() const return height; } +void ImageDataBase::setLinear(bool linear) +{ + this->linear = linear; +} + +bool ImageDataBase::isLinear() const +{ + return linear; +} + } // image } // love diff --git a/src/modules/image/ImageDataBase.h b/src/modules/image/ImageDataBase.h index 0f4f523ee..237f9872f 100644 --- a/src/modules/image/ImageDataBase.h +++ b/src/modules/image/ImageDataBase.h @@ -40,7 +40,8 @@ class ImageDataBase : public Data int getWidth() const; int getHeight() const; - virtual bool isSRGB() const = 0; + void setLinear(bool linear); + bool isLinear() const; protected: @@ -50,6 +51,8 @@ class ImageDataBase : public Data int width; int height; + bool linear; + }; // ImageDataBase } // image diff --git a/src/modules/image/magpie/ASTCHandler.cpp b/src/modules/image/magpie/ASTCHandler.cpp index fb9a395c2..1f56d6d3f 100644 --- a/src/modules/image/magpie/ASTCHandler.cpp +++ b/src/modules/image/magpie/ASTCHandler.cpp @@ -105,7 +105,7 @@ bool ASTCHandler::canParseCompressed(Data *data) return true; } -StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not an .astc file?)"); @@ -138,8 +138,6 @@ StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // ASTCHandler diff --git a/src/modules/image/magpie/KTXHandler.cpp b/src/modules/image/magpie/KTXHandler.cpp index 758642b68..37313735c 100644 --- a/src/modules/image/magpie/KTXHandler.cpp +++ b/src/modules/image/magpie/KTXHandler.cpp @@ -137,10 +137,8 @@ enum KTXGLInternalFormat KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD }; -PixelFormat convertFormat(uint32 glformat, bool &sRGB) +PixelFormat convertFormat(uint32 glformat) { - sRGB = false; - // hnnngg ASTC... switch (glformat) @@ -160,18 +158,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) case KTX_GL_COMPRESSED_RGB8_ETC2: return PIXELFORMAT_ETC2_RGB_UNORM; case KTX_GL_COMPRESSED_SRGB8_ETC2: - sRGB = true; - return PIXELFORMAT_ETC2_RGB_UNORM; + return PIXELFORMAT_ETC2_RGB_sRGB; case KTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return PIXELFORMAT_ETC2_RGBA1_UNORM; case KTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - sRGB = true; - return PIXELFORMAT_ETC2_RGBA1_UNORM; + return PIXELFORMAT_ETC2_RGBA1_sRGB; case KTX_GL_COMPRESSED_RGBA8_ETC2_EAC: return PIXELFORMAT_ETC2_RGBA_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - sRGB = true; - return PIXELFORMAT_ETC2_RGBA_UNORM; + return PIXELFORMAT_ETC2_RGBA_sRGB; // PVRTC. case KTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: @@ -185,15 +180,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // DXT. case KTX_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - sRGB = true; + return PIXELFORMAT_DXT1_sRGB; case KTX_GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return PIXELFORMAT_DXT1_UNORM; case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - sRGB = true; + return PIXELFORMAT_DXT3_sRGB; case KTX_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return PIXELFORMAT_DXT3_UNORM; case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - sRGB = true; + return PIXELFORMAT_DXT5_sRGB; case KTX_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return PIXELFORMAT_DXT5_UNORM; @@ -209,7 +204,7 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // BC6 and BC7. case KTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - sRGB = true; + return PIXELFORMAT_BC7_sRGB; case KTX_GL_COMPRESSED_RGBA_BPTC_UNORM: return PIXELFORMAT_BC7_UNORM; case KTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: @@ -219,59 +214,59 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // ASTC. case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_4x4_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_4x4_KHR: return PIXELFORMAT_ASTC_4x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_5x4_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_5x4_KHR: return PIXELFORMAT_ASTC_5x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_5x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_5x5_KHR: return PIXELFORMAT_ASTC_5x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_6x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_6x5_KHR: return PIXELFORMAT_ASTC_6x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_6x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_6x6_KHR: return PIXELFORMAT_ASTC_6x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x5_KHR: return PIXELFORMAT_ASTC_8x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x6_KHR: return PIXELFORMAT_ASTC_8x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x8_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x8_KHR: return PIXELFORMAT_ASTC_8x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x5_KHR: return PIXELFORMAT_ASTC_10x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x6_KHR: return PIXELFORMAT_ASTC_10x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x8_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x8_KHR: return PIXELFORMAT_ASTC_10x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x10_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x10_KHR: return PIXELFORMAT_ASTC_10x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_12x10_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_12x10_KHR: return PIXELFORMAT_ASTC_12x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_12x12_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_12x12_KHR: return PIXELFORMAT_ASTC_12x12_UNORM; default: @@ -298,7 +293,7 @@ bool KTXHandler::canParseCompressed(Data *data) return true; } -StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a KTX file?)"); @@ -314,8 +309,7 @@ StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector KTXHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // KTXHandler diff --git a/src/modules/image/magpie/PKMHandler.cpp b/src/modules/image/magpie/PKMHandler.cpp index 1fa13283f..746265aa3 100644 --- a/src/modules/image/magpie/PKMHandler.cpp +++ b/src/modules/image/magpie/PKMHandler.cpp @@ -114,7 +114,7 @@ bool PKMHandler::canParseCompressed(Data *data) return true; } -StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a PKM file?)"); @@ -148,8 +148,6 @@ StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // PKMHandler diff --git a/src/modules/image/magpie/PVRHandler.cpp b/src/modules/image/magpie/PVRHandler.cpp index 1259536ca..f30f01b8b 100644 --- a/src/modules/image/magpie/PVRHandler.cpp +++ b/src/modules/image/magpie/PVRHandler.cpp @@ -475,7 +475,7 @@ bool PVRHandler::canParseCompressed(Data *data) return false; } -StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a PVR file?)"); @@ -510,6 +510,9 @@ StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector PVRHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // PVRHandler diff --git a/src/modules/image/magpie/ddsHandler.cpp b/src/modules/image/magpie/ddsHandler.cpp index 974dec24e..cfe903b1d 100644 --- a/src/modules/image/magpie/ddsHandler.cpp +++ b/src/modules/image/magpie/ddsHandler.cpp @@ -32,13 +32,10 @@ namespace image namespace magpie { -static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, bool &bgra) +static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat) { using namespace dds::dxinfo; - sRGB = false; - bgra = false; - switch (dxformat) { case DXGI_FORMAT_R32G32B32A32_TYPELESS: @@ -65,9 +62,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b 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_UNORM; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return PIXELFORMAT_RGBA8_sRGB; case DXGI_FORMAT_R16G16_TYPELESS: case DXGI_FORMAT_R16G16_FLOAT: @@ -98,21 +95,21 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b 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_UNORM; + case DXGI_FORMAT_BC1_UNORM_SRGB: + return PIXELFORMAT_DXT1_sRGB; 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_UNORM; + case DXGI_FORMAT_BC2_UNORM_SRGB: + return PIXELFORMAT_DXT3_sRGB; 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_UNORM; + case DXGI_FORMAT_BC3_UNORM_SRGB: + return PIXELFORMAT_DXT5_sRGB; case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: @@ -136,10 +133,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return PIXELFORMAT_BGRA8_UNORM; case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); - bgra = true; - return PIXELFORMAT_RGBA8_UNORM; + return PIXELFORMAT_BGRA8_sRGB; case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: @@ -150,9 +146,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b 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_UNORM; + case DXGI_FORMAT_BC7_UNORM_SRGB: + return PIXELFORMAT_BC7_sRGB; default: return PIXELFORMAT_UNKNOWN; @@ -164,9 +160,13 @@ bool DDSHandler::canDecode(Data *data) using namespace dds::dxinfo; DXGIFormat dxformat = dds::getDDSPixelFormat(data->getData(), data->getSize()); - bool isSRGB = false; - bool bgra = false; - PixelFormat format = convertFormat(dxformat, isSRGB, bgra); + PixelFormat format = convertFormat(dxformat); + + // We convert BGRA to RGBA + if (format == PIXELFORMAT_BGRA8_UNORM) + format = PIXELFORMAT_RGBA8_UNORM; + else if (format == PIXELFORMAT_BGRA8_sRGB) + format = PIXELFORMAT_RGBA8_sRGB; return ImageData::validPixelFormat(format); } @@ -177,9 +177,19 @@ FormatHandler::DecodedImage DDSHandler::decode(Data *data) dds::Parser parser(data->getData(), data->getSize()); - bool isSRGB = false; + img.format = convertFormat(parser.getFormat()); + bool bgra = false; - img.format = convertFormat(parser.getFormat(), isSRGB, bgra); + if (img.format == PIXELFORMAT_BGRA8_UNORM) + { + img.format = PIXELFORMAT_RGBA8_UNORM; + bgra = true; + } + else if (img.format == PIXELFORMAT_BGRA8_sRGB) + { + img.format = PIXELFORMAT_RGBA8_sRGB; + bgra = true; + } if (!ImageData::validPixelFormat(img.format)) throw love::Exception("Could not parse DDS pixel data: Unsupported format."); @@ -229,14 +239,12 @@ bool DDSHandler::canParseCompressed(Data *data) return dds::isCompressedDDS(data->getData(), data->getSize()); } -StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!dds::isCompressedDDS(filedata->getData(), filedata->getSize())) throw love::Exception("Could not decode compressed data (not a DDS file?)"); PixelFormat texformat = PIXELFORMAT_UNKNOWN; - bool isSRGB = false; - bool bgra = false; size_t dataSize = 0; @@ -245,7 +253,7 @@ StrongRef DDSHandler::parseCompressed(Data *filedata, std::vectorgetData(), filedata->getSize()); - texformat = convertFormat(parser.getFormat(), isSRGB, bgra); + texformat = convertFormat(parser.getFormat()); if (texformat == PIXELFORMAT_UNKNOWN) throw love::Exception("Could not parse compressed data: Unsupported format."); @@ -280,7 +288,6 @@ StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // DDSHandler diff --git a/src/modules/image/wrap_CompressedImageData.cpp b/src/modules/image/wrap_CompressedImageData.cpp index 15f8908e2..ee8655326 100644 --- a/src/modules/image/wrap_CompressedImageData.cpp +++ b/src/modules/image/wrap_CompressedImageData.cpp @@ -103,6 +103,20 @@ int w_CompressedImageData_getFormat(lua_State *L) return 1; } +int w_CompressedImageData_setLinear(lua_State *L) +{ + CompressedImageData *t = luax_checkcompressedimagedata(L, 1); + t->setLinear(luax_checkboolean(L, 2)); + return 0; +} + +int w_CompressedImageData_isLinear(lua_State *L) +{ + CompressedImageData *t = luax_checkcompressedimagedata(L, 1); + luax_pushboolean(L, t->isLinear()); + return 1; +} + static const luaL_Reg w_CompressedImageData_functions[] = { { "clone", w_CompressedImageData_clone }, @@ -111,6 +125,8 @@ static const luaL_Reg w_CompressedImageData_functions[] = { "getDimensions", w_CompressedImageData_getDimensions }, { "getMipmapCount", w_CompressedImageData_getMipmapCount }, { "getFormat", w_CompressedImageData_getFormat }, + { "setLinear", w_CompressedImageData_setLinear }, + { "isLinear", w_CompressedImageData_isLinear }, { 0, 0 }, }; diff --git a/src/modules/image/wrap_ImageData.cpp b/src/modules/image/wrap_ImageData.cpp index 754ad01c5..e717a0fb3 100644 --- a/src/modules/image/wrap_ImageData.cpp +++ b/src/modules/image/wrap_ImageData.cpp @@ -66,6 +66,20 @@ int w_ImageData_getFormat(lua_State *L) return 1; } +int w_ImageData_setLinear(lua_State *L) +{ + ImageData *t = luax_checkimagedata(L, 1); + t->setLinear(luax_checkboolean(L, 2)); + return 0; +} + +int w_ImageData_isLinear(lua_State *L) +{ + ImageData *t = luax_checkimagedata(L, 1); + luax_pushboolean(L, t->isLinear()); + return 1; +} + int w_ImageData_getWidth(lua_State *L) { ImageData *t = luax_checkimagedata(L, 1); @@ -314,6 +328,8 @@ static const luaL_Reg w_ImageData_functions[] = { { "clone", w_ImageData_clone }, { "getFormat", w_ImageData_getFormat }, + { "setLinear", w_ImageData_setLinear }, + { "isLinear", w_ImageData_isLinear }, { "getWidth", w_ImageData_getWidth }, { "getHeight", w_ImageData_getHeight }, { "getDimensions", w_ImageData_getDimensions },