ImageData can track whether they're meant to be loaded into a Texture with a non-sRGB format when gamma correct rendering is enabled.

Fixes #1556.

* Add ImageData/CompressedImageData:setLinear and ImageData/CompressedImageData:isLinear.
  The flag is used as a hint when loading a texture from the data to determine if the format should not be treated as sRGB-encoded. The 'linear' flag in newImage overrides this.

* love.graphics.readbackTexture automatically sets the linear flag on ImageData it returns when the texture's format is linear.
  This allows an ImageData generated via readback to be fed back into a new Texture and the format will match the original Canvas.

* Also clean up some image decoding code.
This commit is contained in:
Sasha Szpakowski
2023-10-14 20:48:21 -03:00
parent bd55100d56
commit 8c13943f64
26 changed files with 149 additions and 105 deletions
+3 -1
View File
@@ -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();
}
}
+1
View File
@@ -103,6 +103,7 @@ protected:
StrongRef<love::image::ImageData> imageData;
Rect rect = {};
PixelFormat textureFormat = PIXELFORMAT_UNKNOWN;
bool isFormatLinear = false;
int imageDataX = 0;
int imageDataY = 0;
+5 -1
View File
@@ -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);