Refactor Blitter state.
Change-Id: Ife3342c64dfc846f8b7722f2e80612fc71f93688
Reviewed-on: https://swiftshader-review.googlesource.com/15128
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index e41b937..dffc10f 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -22,7 +22,7 @@
{
Blitter::Blitter()
{
- blitCache = new RoutineCache<BlitState>(1024);
+ blitCache = new RoutineCache<State>(1024);
}
Blitter::~Blitter()
@@ -38,9 +38,8 @@
}
sw::Surface *color = sw::Surface::create(1, 1, 1, format, pixel, sw::Surface::bytes(format), sw::Surface::bytes(format));
- Blitter::Options clearOptions = static_cast<sw::Blitter::Options>((rgbaMask & 0xF) | CLEAR_OPERATION);
SliceRectF sRect((float)dRect.x0, (float)dRect.y0, (float)dRect.x1, (float)dRect.y1, 0);
- blit(color, sRect, dest, dRect, clearOptions);
+ blit(color, sRect, dest, dRect, {rgbaMask});
delete color;
}
@@ -133,20 +132,6 @@
return true;
}
- void Blitter::blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil)
- {
- Blitter::Options options = WRITE_RGBA;
- if(filter)
- {
- options = static_cast<Blitter::Options>(options | FILTER_LINEAR);
- }
- if(isStencil)
- {
- options = static_cast<Blitter::Options>(options | USE_STENCIL);
- }
- blit(source, sRect, dest, dRect, options);
- }
-
void Blitter::blit(Surface *source, const SliceRectF &sourceRect, Surface *dest, const SliceRect &destRect, const Blitter::Options& options)
{
if(dest->getInternalFormat() == FORMAT_NULL)
@@ -192,7 +177,7 @@
for(int i = dRect.x0; i < dRect.x1; i++)
{
// FIXME: Support RGBA mask
- dest->copyInternal(source, i, j, x, y, (options & FILTER_LINEAR) == FILTER_LINEAR);
+ dest->copyInternal(source, i, j, x, y, options.filter);
x += w;
}
@@ -234,11 +219,11 @@
dest->unlockInternal();
}
- bool Blitter::read(Float4 &c, Pointer<Byte> element, Format format)
+ bool Blitter::read(Float4 &c, Pointer<Byte> element, const State &state)
{
c = Float4(0.0f, 0.0f, 0.0f, 1.0f);
- switch(format)
+ switch(state.sourceFormat)
{
case FORMAT_L8:
c.xyz = Float(Int(*Pointer<Byte>(element)));
@@ -430,15 +415,15 @@
return true;
}
- bool Blitter::write(Float4 &c, Pointer<Byte> element, Format format, const Blitter::Options& options)
+ bool Blitter::write(Float4 &c, Pointer<Byte> element, const State &state)
{
- bool writeR = (options & WRITE_RED) == WRITE_RED;
- bool writeG = (options & WRITE_GREEN) == WRITE_GREEN;
- bool writeB = (options & WRITE_BLUE) == WRITE_BLUE;
- bool writeA = (options & WRITE_ALPHA) == WRITE_ALPHA;
+ bool writeR = state.writeRed;
+ bool writeG = state.writeGreen;
+ bool writeB = state.writeBlue;
+ bool writeA = state.writeAlpha;
bool writeRGBA = writeR && writeG && writeB && writeA;
- switch(format)
+ switch(state.destFormat)
{
case FORMAT_L8:
*Pointer<Byte>(element) = Byte(RoundInt(Float(c.x)));
@@ -553,7 +538,7 @@
if(writeA) { *Pointer<SByte>(element + 3) = SByte(RoundInt(Float(c.w))); }
case FORMAT_X8B8G8R8I:
case FORMAT_X8B8G8R8I_SNORM:
- if(writeA && (format == FORMAT_X8B8G8R8I || format == FORMAT_X8B8G8R8I_SNORM))
+ if(writeA && (state.destFormat == FORMAT_X8B8G8R8I || state.destFormat == FORMAT_X8B8G8R8I_SNORM))
{
*Pointer<SByte>(element + 3) = SByte(0x7F);
}
@@ -568,7 +553,7 @@
case FORMAT_A8B8G8R8UI:
if(writeA) { *Pointer<Byte>(element + 3) = Byte(RoundInt(Float(c.w))); }
case FORMAT_X8B8G8R8UI:
- if(writeA && (format == FORMAT_X8B8G8R8UI))
+ if(writeA && (state.destFormat == FORMAT_X8B8G8R8UI))
{
*Pointer<Byte>(element + 3) = Byte(0xFF);
}
@@ -794,11 +779,11 @@
return true;
}
- bool Blitter::read(Int4 &c, Pointer<Byte> element, Format format)
+ bool Blitter::read(Int4 &c, Pointer<Byte> element, const State &state)
{
c = Int4(0, 0, 0, 1);
- switch(format)
+ switch(state.sourceFormat)
{
case FORMAT_A8B8G8R8I:
c = Insert(c, Int(*Pointer<SByte>(element + 3)), 3);
@@ -857,20 +842,20 @@
return true;
}
- bool Blitter::write(Int4 &c, Pointer<Byte> element, Format format, const Blitter::Options& options)
+ bool Blitter::write(Int4 &c, Pointer<Byte> element, const State &state)
{
- bool writeR = (options & WRITE_RED) == WRITE_RED;
- bool writeG = (options & WRITE_GREEN) == WRITE_GREEN;
- bool writeB = (options & WRITE_BLUE) == WRITE_BLUE;
- bool writeA = (options & WRITE_ALPHA) == WRITE_ALPHA;
+ bool writeR = state.writeRed;
+ bool writeG = state.writeGreen;
+ bool writeB = state.writeBlue;
+ bool writeA = state.writeAlpha;
bool writeRGBA = writeR && writeG && writeB && writeA;
- switch(format)
+ switch(state.destFormat)
{
case FORMAT_A8B8G8R8I:
if(writeA) { *Pointer<SByte>(element + 3) = SByte(Extract(c, 3)); }
case FORMAT_X8B8G8R8I:
- if(writeA && (format != FORMAT_A8B8G8R8I))
+ if(writeA && (state.destFormat != FORMAT_A8B8G8R8I))
{
*Pointer<SByte>(element + 3) = SByte(0x7F);
}
@@ -883,7 +868,7 @@
case FORMAT_A8B8G8R8UI:
if(writeA) { *Pointer<Byte>(element + 3) = Byte(Extract(c, 3)); }
case FORMAT_X8B8G8R8UI:
- if(writeA && (format != FORMAT_A8B8G8R8UI))
+ if(writeA && (state.destFormat != FORMAT_A8B8G8R8UI))
{
*Pointer<Byte>(element + 3) = Byte(0xFF);
}
@@ -896,7 +881,7 @@
case FORMAT_A16B16G16R16I:
if(writeA) { *Pointer<Short>(element + 6) = Short(Extract(c, 3)); }
case FORMAT_X16B16G16R16I:
- if(writeA && (format != FORMAT_A16B16G16R16I))
+ if(writeA && (state.destFormat != FORMAT_A16B16G16R16I))
{
*Pointer<Short>(element + 6) = Short(0x7FFF);
}
@@ -909,7 +894,7 @@
case FORMAT_A16B16G16R16UI:
if(writeA) { *Pointer<UShort>(element + 6) = UShort(Extract(c, 3)); }
case FORMAT_X16B16G16R16UI:
- if(writeA && (format != FORMAT_A16B16G16R16UI))
+ if(writeA && (state.destFormat != FORMAT_A16B16G16R16UI))
{
*Pointer<UShort>(element + 6) = UShort(0xFFFF);
}
@@ -992,7 +977,7 @@
return true;
}
- bool Blitter::GetScale(float4& scale, Format format)
+ bool Blitter::GetScale(float4 &scale, Format format)
{
switch(format)
{
@@ -1085,12 +1070,12 @@
return true;
}
- bool Blitter::ApplyScaleAndClamp(Float4& value, const BlitState& state)
+ bool Blitter::ApplyScaleAndClamp(Float4 &value, const State &state)
{
float4 scale, unscale;
- if(Surface::isNonNormalizedInteger(state.sourceFormat) &&
- !Surface::isNonNormalizedInteger(state.destFormat) &&
- (state.options & CLEAR_OPERATION))
+ if(state.clearOperation &&
+ Surface::isNonNormalizedInteger(state.sourceFormat) &&
+ !Surface::isNonNormalizedInteger(state.destFormat))
{
// If we're clearing a buffer from an int or uint color into a normalized color,
// then the whole range of the int or uint color must be scaled between 0 and 1.
@@ -1134,13 +1119,21 @@
return true;
}
- Int Blitter::ComputeOffset(Int& x, Int& y, Int& pitchB, int bytes, bool quadLayout)
+ Int Blitter::ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout)
{
- return (quadLayout ? (y & Int(~1)) : RValue<Int>(y)) * pitchB +
- (quadLayout ? ((y & Int(1)) << 1) + (x * 2) - (x & Int(1)) : RValue<Int>(x)) * bytes;
+ if(!quadLayout)
+ {
+ return y * pitchB + x * bytes;
+ }
+ else
+ {
+ // (x & ~1) * 2 + (x & 1) == (x - (x & 1)) * 2 + (x & 1) == x * 2 - (x & 1) * 2 + (x & 1) == x * 2 - (x & 1)
+ return (y & Int(~1)) * pitchB +
+ ((y & Int(1)) * 2 + x * 2 - (x & Int(1))) * bytes;
+ }
}
- Routine *Blitter::generate(BlitState &state)
+ Routine *Blitter::generate(const State &state)
{
Function<Void(Pointer<Byte>)> function;
{
@@ -1176,11 +1169,11 @@
Int4 constantColorI;
bool hasConstantColorF = false;
Float4 constantColorF;
- if(state.options & CLEAR_OPERATION)
+ if(state.clearOperation)
{
if(intBoth) // Integer types
{
- if(!read(constantColorI, source, state.sourceFormat))
+ if(!read(constantColorI, source, state))
{
return nullptr;
}
@@ -1188,7 +1181,7 @@
}
else
{
- if(!read(constantColorF, source, state.sourceFormat))
+ if(!read(constantColorF, source, state))
{
return nullptr;
}
@@ -1214,14 +1207,14 @@
if(hasConstantColorI)
{
- if(!write(constantColorI, d, state.destFormat, state.options))
+ if(!write(constantColorI, d, state))
{
return nullptr;
}
}
else if(hasConstantColorF)
{
- if(!write(constantColorF, d, state.destFormat, state.options))
+ if(!write(constantColorF, d, state))
{
return nullptr;
}
@@ -1234,12 +1227,12 @@
Pointer<Byte> s = source + ComputeOffset(X, Y, sPitchB, srcBytes, srcQuadLayout);
- if(!read(color, s, state.sourceFormat))
+ if(!read(color, s, state))
{
return nullptr;
}
- if(!write(color, d, state.destFormat, state.options))
+ if(!write(color, d, state))
{
return nullptr;
}
@@ -1248,14 +1241,14 @@
{
Float4 color;
- if(!(state.options & FILTER_LINEAR) || intSrc)
+ if(!state.filter || intSrc)
{
Int X = Int(x);
Int Y = Int(y);
Pointer<Byte> s = source + ComputeOffset(X, Y, sPitchB, srcBytes, srcQuadLayout);
- if(!read(color, s, state.sourceFormat))
+ if(!read(color, s, state))
{
return nullptr;
}
@@ -1278,10 +1271,10 @@
Pointer<Byte> s10 = source + ComputeOffset(X0, Y1, sPitchB, srcBytes, srcQuadLayout);
Pointer<Byte> s11 = source + ComputeOffset(X1, Y1, sPitchB, srcBytes, srcQuadLayout);
- Float4 c00; if(!read(c00, s00, state.sourceFormat)) return nullptr;
- Float4 c01; if(!read(c01, s01, state.sourceFormat)) return nullptr;
- Float4 c10; if(!read(c10, s10, state.sourceFormat)) return nullptr;
- Float4 c11; if(!read(c11, s11, state.sourceFormat)) return nullptr;
+ Float4 c00; if(!read(c00, s00, state)) return nullptr;
+ Float4 c01; if(!read(c01, s01, state)) return nullptr;
+ Float4 c10; if(!read(c10, s10, state)) return nullptr;
+ Float4 c11; if(!read(c11, s11, state)) return nullptr;
Float4 fx = Float4(x0 - Float(X0));
Float4 fy = Float4(y0 - Float(Y0));
@@ -1299,7 +1292,7 @@
for(int s = 0; s < state.destSamples; s++)
{
- if(!write(color, d, state.destFormat, state.options))
+ if(!write(color, d, state))
{
return nullptr;
}
@@ -1318,9 +1311,9 @@
return function(L"BlitRoutine");
}
- bool Blitter::blitReactor(Surface *source, const SliceRectF &sourceRect, Surface *dest, const SliceRect &destRect, const Blitter::Options& options)
+ bool Blitter::blitReactor(Surface *source, const SliceRectF &sourceRect, Surface *dest, const SliceRect &destRect, const Blitter::Options &options)
{
- ASSERT(!(options & CLEAR_OPERATION) || ((source->getWidth() == 1) && (source->getHeight() == 1) && (source->getDepth() == 1)));
+ ASSERT(!options.clearOperation || ((source->getWidth() == 1) && (source->getHeight() == 1) && (source->getDepth() == 1)));
Rect dRect = destRect;
RectF sRect = sourceRect;
@@ -1335,16 +1328,15 @@
swap(sRect.y0, sRect.y1);
}
- BlitState state;
+ State state(options);
bool useSourceInternal = !source->isExternalDirty();
bool useDestInternal = !dest->isExternalDirty();
- bool isStencil = ((options & USE_STENCIL) == USE_STENCIL);
+ bool isStencil = options.useStencil;
state.sourceFormat = isStencil ? source->getStencilFormat() : source->getFormat(useSourceInternal);
state.destFormat = isStencil ? dest->getStencilFormat() : dest->getFormat(useDestInternal);
state.destSamples = dest->getSamples();
- state.options = options;
criticalSection.lock();
Routine *blitRoutine = blitCache->query(state);
@@ -1368,7 +1360,7 @@
BlitData data;
- bool isRGBA = ((options & WRITE_RGBA) == WRITE_RGBA);
+ bool isRGBA = options.writeMask == 0xF;
bool isEntireDest = dest->isEntire(destRect);
data.source = isStencil ? source->lockStencil(0, 0, 0, sw::PUBLIC) :
diff --git a/src/Renderer/Blitter.hpp b/src/Renderer/Blitter.hpp
index 6e87db8..66ef1f8 100644
--- a/src/Renderer/Blitter.hpp
+++ b/src/Renderer/Blitter.hpp
@@ -25,30 +25,45 @@
{
class Blitter
{
- enum Options : unsigned char
+ struct Options
{
- FILTER_POINT = 0x00,
- WRITE_RED = 0x01,
- WRITE_GREEN = 0x02,
- WRITE_BLUE = 0x04,
- WRITE_ALPHA = 0x08,
- WRITE_RGBA = WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA,
- FILTER_LINEAR = 0x10,
- CLEAR_OPERATION = 0x20,
- USE_STENCIL = 0x40,
+ Options() {}
+ Options(bool filter, bool useStencil)
+ : writeMask(0xF), clearOperation(false), filter(filter), useStencil(useStencil) {}
+ Options(unsigned int writeMask)
+ : writeMask(writeMask), clearOperation(true), filter(false), useStencil(false) {}
+
+ union
+ {
+ struct
+ {
+ bool writeRed : 1;
+ bool writeGreen : 1;
+ bool writeBlue : 1;
+ bool writeAlpha : 1;
+ };
+
+ unsigned char writeMask;
+ };
+
+ bool clearOperation : 1;
+ bool filter : 1;
+ bool useStencil : 1;
};
- struct BlitState
+ struct State : Options
{
- bool operator==(const BlitState &state) const
+ State() {}
+ State(const Options &options) : Options(options) {}
+
+ bool operator==(const State &state) const
{
- return memcmp(this, &state, sizeof(BlitState)) == 0;
+ return memcmp(this, &state, sizeof(State)) == 0;
}
Format sourceFormat;
Format destFormat;
int destSamples;
- Blitter::Options options;
};
struct BlitData
@@ -78,24 +93,23 @@
virtual ~Blitter();
void clear(void *pixel, sw::Format format, Surface *dest, const SliceRect &dRect, 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, const Options &options);
void blit3D(Surface *source, Surface *dest);
private:
bool fastClear(void *pixel, sw::Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask);
- bool read(Float4 &color, Pointer<Byte> element, Format format);
- bool write(Float4 &color, Pointer<Byte> element, Format format, const Blitter::Options& options);
- bool read(Int4 &color, Pointer<Byte> element, Format format);
- bool write(Int4 &color, Pointer<Byte> element, Format format, const Blitter::Options& options);
+ bool read(Float4 &color, Pointer<Byte> element, const State &state);
+ bool write(Float4 &color, Pointer<Byte> element, const State &state);
+ 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 BlitState& state);
- static Int ComputeOffset(Int& x, Int& y, Int& pitchB, int bytes, bool quadLayout);
- void blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, const Blitter::Options& options);
- bool blitReactor(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, const Blitter::Options& options);
- Routine *generate(BlitState &state);
+ static bool ApplyScaleAndClamp(Float4 &value, const State &state);
+ static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout);
+ bool blitReactor(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, const Options &options);
+ Routine *generate(const State &state);
- RoutineCache<BlitState> *blitCache;
+ RoutineCache<State> *blitCache;
MutexLock criticalSection;
};
}
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index 1c92576..ffdb547 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -684,7 +684,7 @@
void Renderer::blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil)
{
- blitter->blit(source, sRect, dest, dRect, filter, isStencil);
+ blitter->blit(source, sRect, dest, dRect, {filter, isStencil});
}
void Renderer::blit3D(Surface *source, Surface *dest)
diff --git a/src/Shader/PixelRoutine.cpp b/src/Shader/PixelRoutine.cpp
index 949fbfc..a5b6f56 100644
--- a/src/Shader/PixelRoutine.cpp
+++ b/src/Shader/PixelRoutine.cpp
@@ -991,7 +991,7 @@
bool PixelRoutine::isSRGB(int index) const
{
- return state.targetFormat[index] == FORMAT_SRGB8_A8 || state.targetFormat[index] == FORMAT_SRGB8_X8;
+ return Surface::isSRGBformat(state.targetFormat[index]);
}
void PixelRoutine::readPixel(int index, Pointer<Byte> &cBuffer, Int &x, Vector4s &pixel)
@@ -2653,17 +2653,12 @@
void PixelRoutine::sRGBtoLinear16_12_16(Vector4s &c)
{
+ Pointer<Byte> LUT = constants + OFFSET(Constants,sRGBtoLinear12_16);
+
c.x = As<UShort4>(c.x) >> 4;
c.y = As<UShort4>(c.y) >> 4;
c.z = As<UShort4>(c.z) >> 4;
- sRGBtoLinear12_16(c);
- }
-
- void PixelRoutine::sRGBtoLinear12_16(Vector4s &c)
- {
- Pointer<Byte> LUT = constants + OFFSET(Constants,sRGBtoLinear12_16);
-
c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 0))), 0);
c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 1))), 1);
c.x = Insert(c.x, *Pointer<Short>(LUT + 2 * Int(Extract(c.x, 2))), 2);
diff --git a/src/Shader/PixelRoutine.hpp b/src/Shader/PixelRoutine.hpp
index bc558c2..1cd076e 100644
--- a/src/Shader/PixelRoutine.hpp
+++ b/src/Shader/PixelRoutine.hpp
@@ -83,7 +83,6 @@
void writeDepth(Pointer<Byte> &zBuffer, int q, Int &x, Float4 &z, Int &zMask);
void sRGBtoLinear16_12_16(Vector4s &c);
- void sRGBtoLinear12_16(Vector4s &c);
void linearToSRGB16_12_16(Vector4s &c);
Float4 sRGBtoLinear(const Float4 &x);