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
sw::Surface *externalSurface = sw::Surface::create(width, height, 1, egl::ConvertFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
sw::SliceRectF sliceRect(rect);
sw::SliceRect dstSliceRect(dstRect);
device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false);
device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false, false, false);
delete externalSurface;
renderTarget->release();
......
......@@ -14,6 +14,7 @@
#include "Blitter.hpp"
#include "Shader/ShaderCore.hpp"
#include "Reactor/Reactor.hpp"
#include "Common/Memory.hpp"
#include "Common/Debug.hpp"
......@@ -1101,7 +1102,25 @@ namespace sw
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);
}
......@@ -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)
{
Function<Void(Pointer<Byte>)> function;
......
......@@ -28,10 +28,10 @@ namespace sw
struct Options
{
Options() {}
Options(bool filter, bool useStencil)
: writeMask(0xF), clearOperation(false), filter(filter), useStencil(useStencil) {}
Options(bool filter, bool useStencil, bool convertSRGB)
: writeMask(0xF), clearOperation(false), filter(filter), useStencil(useStencil), convertSRGB(convertSRGB) {}
Options(unsigned int writeMask)
: writeMask(writeMask), clearOperation(true), filter(false), useStencil(false) {}
: writeMask(writeMask), clearOperation(true), filter(false), useStencil(false), convertSRGB(true) {}
union
{
......@@ -49,6 +49,7 @@ namespace sw
bool clearOperation : 1;
bool filter : 1;
bool useStencil : 1;
bool convertSRGB : 1;
};
struct State : Options
......@@ -106,6 +107,8 @@ namespace sw
static bool GetScale(float4& scale, Format format);
static bool ApplyScaleAndClamp(Float4 &value, const State &state);
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);
Routine *generate(const State &state);
......
......@@ -682,9 +682,9 @@ namespace sw
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)
......
......@@ -322,7 +322,7 @@ namespace sw
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 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 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