Fix sRGB linear filtering in blitter
Fixed sRGB filtering by performing the conversion
pre-filtering when appropriate.
Change-Id: Id24898feed7e9a7dadff45431198771af25efed7
Reviewed-on: https://swiftshader-review.googlesource.com/15409
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index 6f9d3a4..efb2cad 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -1074,7 +1074,7 @@
return true;
}
- bool Blitter::ApplyScaleAndClamp(Float4 &value, const State &state)
+ bool Blitter::ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled)
{
float4 scale, unscale;
if(state.clearOperation &&
@@ -1108,20 +1108,12 @@
bool srcSRGB = Surface::isSRGBformat(state.sourceFormat);
bool dstSRGB = Surface::isSRGBformat(state.destFormat);
- if(state.convertSRGB && (srcSRGB ^ dstSRGB)) // One of the formats is sRGB encoded.
+ if(state.convertSRGB && ((srcSRGB && !preScaled) || dstSRGB)) // One of the formats is sRGB encoded.
{
- value = value * Float4(1.0f / unscale.x, 1.0f / unscale.y, 1.0f / unscale.z, 1.0f / unscale.w);
-
- if(srcSRGB)
- {
- value = sRGBtoLinear(value);
- }
- else // dstSRGB
- {
- value = LinearToSRGB(value);
- }
-
- value = value * Float4(scale.x, scale.y, scale.z, scale.w);
+ value *= preScaled ? Float4(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z, 1.0f / scale.w) : // Unapply scale
+ Float4(1.0f / unscale.x, 1.0f / unscale.y, 1.0f / unscale.z, 1.0f / unscale.w); // Apply unscale
+ value = (srcSRGB && !preScaled) ? sRGBtoLinear(value) : LinearToSRGB(value);
+ value *= Float4(scale.x, scale.y, scale.z, scale.w); // Apply scale
}
else if(unscale != scale)
{
@@ -1297,6 +1289,7 @@
{
Float4 color;
+ bool preScaled = false;
if(!state.filter || intSrc)
{
Int X = Int(x);
@@ -1347,6 +1340,15 @@
Float4 c10; if(!read(c10, s10, state)) return nullptr;
Float4 c11; if(!read(c11, s11, state)) return nullptr;
+ if(state.convertSRGB && Surface::isSRGBformat(state.sourceFormat)) // sRGB -> RGB
+ {
+ if(!ApplyScaleAndClamp(c00, state)) return nullptr;
+ if(!ApplyScaleAndClamp(c01, state)) return nullptr;
+ if(!ApplyScaleAndClamp(c10, state)) return nullptr;
+ if(!ApplyScaleAndClamp(c11, state)) return nullptr;
+ preScaled = true;
+ }
+
Float4 fx = Float4(x0 - Float(X0));
Float4 fy = Float4(y0 - Float(Y0));
Float4 ix = Float4(1.0f) - fx;
@@ -1356,7 +1358,7 @@
(c10 * ix + c11 * fx) * fy;
}
- if(!ApplyScaleAndClamp(color, state))
+ if(!ApplyScaleAndClamp(color, state, preScaled))
{
return nullptr;
}
diff --git a/src/Renderer/Blitter.hpp b/src/Renderer/Blitter.hpp
index c411c09..e3db745 100644
--- a/src/Renderer/Blitter.hpp
+++ b/src/Renderer/Blitter.hpp
@@ -106,7 +106,7 @@
bool read(Int4 &color, Pointer<Byte> element, const State &state);
bool write(Int4 &color, Pointer<Byte> element, const State &state);
static bool GetScale(float4& scale, Format format);
- static bool ApplyScaleAndClamp(Float4 &value, const State &state);
+ static bool ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false);
static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout);
static Float4 LinearToSRGB(Float4 &color);
static Float4 sRGBtoLinear(Float4 &color);