Commit 1ab837c5 by Nicolas Capens Committed by Nicolas Capens

Implement sRGB conversion in the blitter.

Note that glReadPixels() does not perform sRGB conversion. Change-Id: I3f9089b79652ce42cb5695d5b6a8ce92d15c27a8 Reviewed-on: https://swiftshader-review.googlesource.com/14492Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 8f7739a8
...@@ -3341,7 +3341,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum ...@@ -3341,7 +3341,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
sw::Surface *externalSurface = sw::Surface::create(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight); sw::Surface *externalSurface = sw::Surface::create(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
sw::SliceRectF sliceRect(rect); sw::SliceRectF sliceRect(rect);
sw::SliceRect dstSliceRect(dstRect); sw::SliceRect dstSliceRect(dstRect);
device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false); device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false, false, false);
delete externalSurface; delete externalSurface;
renderTarget->release(); renderTarget->release();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "Blitter.hpp" #include "Blitter.hpp"
#include "Shader/ShaderCore.hpp"
#include "Reactor/Reactor.hpp" #include "Reactor/Reactor.hpp"
#include "Common/Memory.hpp" #include "Common/Memory.hpp"
#include "Common/Debug.hpp" #include "Common/Debug.hpp"
...@@ -1101,7 +1102,25 @@ namespace sw ...@@ -1101,7 +1102,25 @@ namespace sw
return false; return false;
} }
if(unscale != scale) bool srcSRGB = Surface::isSRGBformat(state.sourceFormat);
bool dstSRGB = Surface::isSRGBformat(state.destFormat);
if(state.convertSRGB && (srcSRGB ^ 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);
}
else if(unscale != scale)
{ {
value *= Float4(scale.x / unscale.x, scale.y / unscale.y, scale.z / unscale.z, scale.w / unscale.w); value *= Float4(scale.x / unscale.x, scale.y / unscale.y, scale.z / unscale.z, scale.w / unscale.w);
} }
...@@ -1133,6 +1152,30 @@ namespace sw ...@@ -1133,6 +1152,30 @@ namespace sw
} }
} }
Float4 Blitter::LinearToSRGB(Float4 &c)
{
Float4 lc = Min(c, Float4(0.0031308f)) * Float4(12.92f);
Float4 ec = Float4(1.055f) * power(c, Float4(1.0f / 2.4f)) - Float4(0.055f);
Float4 s = c;
s.xyz = Max(lc, ec);
return s;
}
Float4 Blitter::sRGBtoLinear(Float4 &c)
{
Float4 lc = c * Float4(1.0f / 12.92f);
Float4 ec = power((c + Float4(0.055f)) * Float4(1.0f / 1.055f), Float4(2.4f));
Int4 linear = CmpLT(c, Float4(0.04045f));
Float4 s = c;
s.xyz = As<Float4>((linear & As<Int4>(lc)) | (~linear & As<Int4>(ec))); // FIXME: IfThenElse()
return s;
}
Routine *Blitter::generate(const State &state) Routine *Blitter::generate(const State &state)
{ {
Function<Void(Pointer<Byte>)> function; Function<Void(Pointer<Byte>)> function;
......
...@@ -28,10 +28,10 @@ namespace sw ...@@ -28,10 +28,10 @@ namespace sw
struct Options struct Options
{ {
Options() {} Options() {}
Options(bool filter, bool useStencil) Options(bool filter, bool useStencil, bool convertSRGB)
: writeMask(0xF), clearOperation(false), filter(filter), useStencil(useStencil) {} : writeMask(0xF), clearOperation(false), filter(filter), useStencil(useStencil), convertSRGB(convertSRGB) {}
Options(unsigned int writeMask) Options(unsigned int writeMask)
: writeMask(writeMask), clearOperation(true), filter(false), useStencil(false) {} : writeMask(writeMask), clearOperation(true), filter(false), useStencil(false), convertSRGB(true) {}
union union
{ {
...@@ -49,6 +49,7 @@ namespace sw ...@@ -49,6 +49,7 @@ namespace sw
bool clearOperation : 1; bool clearOperation : 1;
bool filter : 1; bool filter : 1;
bool useStencil : 1; bool useStencil : 1;
bool convertSRGB : 1;
}; };
struct State : Options struct State : Options
...@@ -106,6 +107,8 @@ namespace sw ...@@ -106,6 +107,8 @@ namespace sw
static bool GetScale(float4& scale, Format format); static bool GetScale(float4& scale, Format format);
static bool ApplyScaleAndClamp(Float4 &value, const State &state); static bool ApplyScaleAndClamp(Float4 &value, const State &state);
static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout); static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout);
static Float4 LinearToSRGB(Float4 &color);
static Float4 sRGBtoLinear(Float4 &color);
bool blitReactor(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, const Options &options); bool blitReactor(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, const Options &options);
Routine *generate(const State &state); Routine *generate(const State &state);
......
...@@ -682,9 +682,9 @@ namespace sw ...@@ -682,9 +682,9 @@ namespace sw
blitter->clear(value, format, dest, clearRect, rgbaMask); blitter->clear(value, format, dest, clearRect, rgbaMask);
} }
void Renderer::blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil) void Renderer::blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil, bool sRGBconversion)
{ {
blitter->blit(source, sRect, dest, dRect, {filter, isStencil}); blitter->blit(source, sRect, dest, dRect, {filter, isStencil, sRGBconversion});
} }
void Renderer::blit3D(Surface *source, Surface *dest) void Renderer::blit3D(Surface *source, Surface *dest)
......
...@@ -322,7 +322,7 @@ namespace sw ...@@ -322,7 +322,7 @@ namespace sw
void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true); void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
void clear(void *value, Format format, Surface *dest, const Rect &rect, unsigned int rgbaMask); void clear(void *value, Format format, Surface *dest, const Rect &rect, unsigned int rgbaMask);
void blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false); void blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false, bool sRGBconversion = true);
void blit3D(Surface *source, Surface *dest); void blit3D(Surface *source, Surface *dest);
void setIndexBuffer(Resource *indexBuffer); void setIndexBuffer(Resource *indexBuffer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment