Commit 8f7739a8 by Nicolas Capens Committed by Nicolas Capens

Refactor Blitter state.

Change-Id: Ife3342c64dfc846f8b7722f2e80612fc71f93688 Reviewed-on: https://swiftshader-review.googlesource.com/15128Tested-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 1efac529
......@@ -22,7 +22,7 @@ namespace sw
{
Blitter::Blitter()
{
blitCache = new RoutineCache<BlitState>(1024);
blitCache = new RoutineCache<State>(1024);
}
Blitter::~Blitter()
......@@ -38,9 +38,8 @@ namespace sw
}
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
return true;
}
bool Blitter::GetScale(float4& scale, Format format)
bool Blitter::GetScale(float4 &scale, Format format)
{
switch(format)
{
......@@ -1085,12 +1070,12 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
}
else
{
if(!read(constantColorF, source, state.sourceFormat))
if(!read(constantColorF, source, state))
{
return nullptr;
}
......@@ -1214,14 +1207,14 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
{
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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 @@ namespace sw
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) :
......
......@@ -25,30 +25,45 @@ namespace sw
{
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 @@ namespace sw
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;
};
}
......
......@@ -684,7 +684,7 @@ namespace sw
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)
......
......@@ -991,7 +991,7 @@ namespace sw
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 @@ namespace sw
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);
......
......@@ -83,7 +83,6 @@ namespace sw
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);
......
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