Commit 43577b8c by Alexis Hetu Committed by Alexis Hétu

Integer types support in Blitter

The blitter now supports integer types. This means: - It supports conversions to/from integer types from/to other already supported types. - It supports integer to integer conversions without going to an intermediate float format. Also added a Blitter::GetScale() function to avoid having 2 instances of the same switch statement in the code and added the read/write utility functions. The final Blitter code is not longer peppered with switch statements and is, hopefully, easier to read that way. Change-Id: I80de519aaaa768f8cedd98f97dc4414dda75bf54 Reviewed-on: https://swiftshader-review.googlesource.com/4113Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent a60d825a
...@@ -216,18 +216,7 @@ namespace D3D9 ...@@ -216,18 +216,7 @@ namespace D3D9
for(int i = 0; i < dWidth; i++) for(int i = 0; i < dWidth; i++)
{ {
sw::Color<float> color; dest->copyInternal(source, i, j, k, x, y, z, filter > D3DTEXF_POINT);
if(filter <= D3DTEXF_POINT)
{
color = source->readInternal((int)x, (int)y, (int)z);
}
else // filter >= D3DTEXF_LINEAR
{
color = source->sampleInternal(x, y, z);
}
dest->writeInternal(i, j, k, color);
x += w; x += w;
} }
......
...@@ -67,18 +67,7 @@ namespace sw ...@@ -67,18 +67,7 @@ namespace sw
for(int i = dRect.x0; i < dRect.x1; i++) for(int i = dRect.x0; i < dRect.x1; i++)
{ {
sw::Color<float> color; dest->copyInternal(source, i, j, x, y, filter);
if(!filter)
{
color = source->readInternal((int)x, (int)y);
}
else // Bilinear filtering
{
color = source->sampleInternal(x, y);
}
dest->writeInternal(i, j, color);
x += w; x += w;
} }
...@@ -108,7 +97,7 @@ namespace sw ...@@ -108,7 +97,7 @@ namespace sw
float x = 0.5f * w; float x = 0.5f * w;
for(int i = 0; i < dest->getWidth(); ++i) for(int i = 0; i < dest->getWidth(); ++i)
{ {
dest->writeInternal(i, j, k, source->sampleInternal(x, y, z)); dest->copyInternal(source, i, j, k, x, y, z, true);
x += w; x += w;
} }
y += h; y += h;
...@@ -133,9 +122,50 @@ namespace sw ...@@ -133,9 +122,50 @@ namespace sw
c.xyz = 0.0f; c.xyz = 0.0f;
c.w = Float(Int(*Pointer<Byte>(element))); c.w = Float(Int(*Pointer<Byte>(element)));
break; break;
case FORMAT_R8I:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<SByte>(element)));
break;
case FORMAT_R8UI:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<Byte>(element)));
break;
case FORMAT_R8I_SNORM:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<SByte>(element)));
break;
case FORMAT_R8:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<Byte>(element)));
break;
case FORMAT_R16I:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<Short>(element)));
break;
case FORMAT_R16UI:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<UShort>(element)));
break;
case FORMAT_R32I:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<Int>(element)));
break;
case FORMAT_R32UI:
c.yzw = 0.0f;
c.x = Float(Int(*Pointer<UInt>(element)));
break;
case FORMAT_A8R8G8B8: case FORMAT_A8R8G8B8:
c = Float4(*Pointer<Byte4>(element)).zyxw; c = Float4(*Pointer<Byte4>(element)).zyxw;
break; break;
case FORMAT_A8B8G8R8I:
c = Float4(*Pointer<SByte4>(element));
break;
case FORMAT_A8B8G8R8UI:
c = Float4(*Pointer<Byte4>(element));
break;
case FORMAT_A8B8G8R8I_SNORM:
c = Float4(*Pointer<SByte4>(element));
break;
case FORMAT_A8B8G8R8: case FORMAT_A8B8G8R8:
c = Float4(*Pointer<Byte4>(element)); c = Float4(*Pointer<Byte4>(element));
break; break;
...@@ -143,18 +173,84 @@ namespace sw ...@@ -143,18 +173,84 @@ namespace sw
c = Float4(*Pointer<Byte4>(element)).zyxw; c = Float4(*Pointer<Byte4>(element)).zyxw;
c.w = 1.0f; c.w = 1.0f;
break; break;
case FORMAT_X8B8G8R8I:
c = Float4(*Pointer<SByte4>(element));
c.w = 1.0f;
break;
case FORMAT_X8B8G8R8UI:
c = Float4(*Pointer<Byte4>(element));
c.w = 1.0f;
break;
case FORMAT_X8B8G8R8I_SNORM:
c = Float4(*Pointer<SByte4>(element));
c.w = 1.0f;
break;
case FORMAT_X8B8G8R8: case FORMAT_X8B8G8R8:
c = Float4(*Pointer<Byte4>(element)); c = Float4(*Pointer<Byte4>(element));
c.w = 1.0f; c.w = 1.0f;
break; break;
case FORMAT_A16B16G16R16I:
c = Float4(*Pointer<Short4>(element));
break;
case FORMAT_A16B16G16R16: case FORMAT_A16B16G16R16:
case FORMAT_A16B16G16R16UI:
c = Float4(*Pointer<UShort4>(element));
break;
case FORMAT_X16B16G16R16I:
c = Float4(*Pointer<Short4>(element));
c.w = 1.0f;
break;
case FORMAT_X16B16G16R16UI:
c = Float4(*Pointer<UShort4>(element)); c = Float4(*Pointer<UShort4>(element));
c.w = 1.0f;
break;
case FORMAT_A32B32G32R32I:
c = Float4(*Pointer<Int4>(element));
break;
case FORMAT_A32B32G32R32UI:
c = Float4(*Pointer<UInt4>(element));
break;
case FORMAT_X32B32G32R32I:
c = Float4(*Pointer<Int4>(element));
c.w = 1.0f;
break;
case FORMAT_X32B32G32R32UI:
c = Float4(*Pointer<UInt4>(element));
c.w = 1.0f;
break;
case FORMAT_G8R8I:
c.x = Float(Int(*Pointer<SByte>(element + 0)));
c.y = Float(Int(*Pointer<SByte>(element + 1)));
break;
case FORMAT_G8R8UI:
c.x = Float(Int(*Pointer<Byte>(element + 0)));
c.y = Float(Int(*Pointer<Byte>(element + 1)));
break;
case FORMAT_G8R8I_SNORM:
c.x = Float(Int(*Pointer<SByte>(element + 0)));
c.y = Float(Int(*Pointer<SByte>(element + 1)));
break;
case FORMAT_G8R8:
c.x = Float(Int(*Pointer<Byte>(element + 0)));
c.y = Float(Int(*Pointer<Byte>(element + 1)));
break;
case FORMAT_G16R16I:
c.x = Float(Int(*Pointer<Short>(element + 0)));
c.y = Float(Int(*Pointer<Short>(element + 2)));
break; break;
case FORMAT_G16R16: case FORMAT_G16R16:
// FIXME: Optimize case FORMAT_G16R16UI:
c.x = Float(Int(*Pointer<UShort>(element + 0))); c.x = Float(Int(*Pointer<UShort>(element + 0)));
c.y = Float(Int(*Pointer<UShort>(element + 2))); c.y = Float(Int(*Pointer<UShort>(element + 2)));
break; break;
case FORMAT_G32R32I:
c.x = Float(Int(*Pointer<Int>(element + 0)));
c.y = Float(Int(*Pointer<Int>(element + 4)));
break;
case FORMAT_G32R32UI:
c.x = Float(Int(*Pointer<UInt>(element + 0)));
c.y = Float(Int(*Pointer<UInt>(element + 4)));
break;
case FORMAT_A32B32G32R32F: case FORMAT_A32B32G32R32F:
c = *Pointer<Float4>(element); c = *Pointer<Float4>(element);
break; break;
...@@ -172,6 +268,380 @@ namespace sw ...@@ -172,6 +268,380 @@ namespace sw
return true; return true;
} }
bool Blitter::write(Float4 &c, Pointer<Byte> element, Format format)
{
switch(format)
{
case FORMAT_L8:
*Pointer<Byte>(element) = Byte(RoundInt(Float(c.x)));
break;
case FORMAT_A8:
*Pointer<Byte>(element) = Byte(RoundInt(Float(c.w)));
break;
case FORMAT_A8R8G8B8:
{
UShort4 c0 = As<UShort4>(RoundShort4(c.zyxw));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(element) = UInt(As<Long>(c1));
}
break;
case FORMAT_A8B8G8R8:
{
UShort4 c0 = As<UShort4>(RoundShort4(c));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(element) = UInt(As<Long>(c1));
}
break;
case FORMAT_X8R8G8B8:
{
UShort4 c0 = As<UShort4>(RoundShort4(c.zyxw));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(element) = UInt(As<Long>(c1)) | 0xFF000000;
}
break;
case FORMAT_X8B8G8R8:
{
UShort4 c0 = As<UShort4>(RoundShort4(c));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(element) = UInt(As<Long>(c1)) | 0xFF000000;
}
break;
case FORMAT_A32B32G32R32F:
*Pointer<Float4>(element) = c;
break;
case FORMAT_G32R32F:
*Pointer<Float2>(element) = Float2(c);
break;
case FORMAT_R32F:
*Pointer<Float>(element) = c.x;
break;
case FORMAT_A8B8G8R8I:
case FORMAT_A8B8G8R8I_SNORM:
*Pointer<SByte>(element + 3) = As<SByte>(RoundInt(Float(c.w)));
case FORMAT_X8B8G8R8I:
case FORMAT_X8B8G8R8I_SNORM:
if(format == FORMAT_X8B8G8R8I || format == FORMAT_X8B8G8R8I_SNORM)
{
*Pointer<SByte>(element + 3) = SByte(0x7F);
}
*Pointer<SByte>(element + 2) = As<SByte>(RoundInt(Float(c.z)));
case FORMAT_G8R8I:
case FORMAT_G8R8I_SNORM:
*Pointer<SByte>(element + 1) = As<SByte>(RoundInt(Float(c.y)));
case FORMAT_R8I:
case FORMAT_R8I_SNORM:
*Pointer<SByte>(element) = As<SByte>(RoundInt(Float(c.x)));
break;
case FORMAT_A8B8G8R8UI:
*Pointer<Byte>(element + 3) = As<Byte>(UInt(Float(c.w) + Float(0.5f)));
case FORMAT_X8B8G8R8UI:
if(format == FORMAT_X8B8G8R8UI)
{
*Pointer<Byte>(element + 3) = Byte(0xFF);
}
*Pointer<Byte>(element + 2) = As<Byte>(UInt(Float(c.z) + Float(0.5f)));
case FORMAT_G8R8UI:
case FORMAT_G8R8:
*Pointer<Byte>(element + 1) = As<Byte>(UInt(Float(c.y) + Float(0.5f)));
case FORMAT_R8UI:
case FORMAT_R8:
*Pointer<Byte>(element) = As<Byte>(UInt(Float(c.x) + Float(0.5f)));
break;
case FORMAT_A16B16G16R16I:
*Pointer<Short4>(element) = Short4(RoundInt(c));
break;
case FORMAT_X16B16G16R16I:
*Pointer<Short4>(element) = Short4(RoundInt(c));
*Pointer<Short>(element + 6) = Short(0x7F);
break;
case FORMAT_G16R16I:
*Pointer<UInt>(element) = UInt(As<Long>(Short4(RoundInt(c))));
break;
case FORMAT_R16I:
*Pointer<Short>(element) = As<Short>(RoundInt(Float(c.x)));
break;
case FORMAT_A16B16G16R16UI:
case FORMAT_A16B16G16R16:
*Pointer<UShort4>(element) = UShort4(RoundInt(c));
break;
case FORMAT_X16B16G16R16UI:
*Pointer<UShort4>(element) = UShort4(RoundInt(c));
*Pointer<UShort>(element + 6) = UShort(0xFF);
break;
case FORMAT_G16R16UI:
case FORMAT_G16R16:
*Pointer<UInt>(element) = UInt(As<Long>(UShort4(RoundInt(c))));
case FORMAT_R16UI:
*Pointer<UShort>(element) = As<UShort>(UInt(Float(c.x) + Float(0.5f)));
break;
case FORMAT_A32B32G32R32I:
*Pointer<Int4>(element) = RoundInt(c);
break;
case FORMAT_X32B32G32R32I:
*Pointer<Int4>(element) = RoundInt(c);
*Pointer<Int>(element + 12) = Int(0x7FFFFFFF);
break;
case FORMAT_G32R32I:
*Pointer<Int>(element + 4) = RoundInt(Float(c.y));
case FORMAT_R32I:
*Pointer<Int>(element) = RoundInt(Float(c.x));
break;
case FORMAT_A32B32G32R32UI:
*Pointer<UInt4>(element) = UInt4(c + Float4(0.5f));
break;
case FORMAT_X32B32G32R32UI:
*Pointer<UInt4>(element) = UInt4(c + Float4(0.5f));
*Pointer<UInt4>(element + 12) = UInt4(0xFFFFFFFF);
break;
case FORMAT_G32R32UI:
*Pointer<UInt>(element + 4) = UInt(Float(c.y) + Float(0.5f));
case FORMAT_R32UI:
*Pointer<UInt>(element) = UInt(Float(c.x) + Float(0.5f));
break;
default:
return false;
}
return true;
}
bool Blitter::read(Int4 &c, Pointer<Byte> element, Format format)
{
c = Int4(0);
switch(format)
{
case FORMAT_A8B8G8R8I:
Insert(c, Int(*Pointer<SByte>(element + 3)), 3);
case FORMAT_X8B8G8R8I:
Insert(c, Int(*Pointer<SByte>(element + 2)), 2);
case FORMAT_G8R8I:
Insert(c, Int(*Pointer<SByte>(element + 1)), 1);
case FORMAT_R8I:
Insert(c, Int(*Pointer<SByte>(element)), 0);
if(format != FORMAT_A8B8G8R8I)
{
Insert(c, Int(0x7F), 3); // Set alpha
}
break;
case FORMAT_A8B8G8R8UI:
Insert(c, Int(*Pointer<Byte>(element + 3)), 3);
case FORMAT_X8B8G8R8UI:
Insert(c, Int(*Pointer<Byte>(element + 2)), 2);
case FORMAT_G8R8UI:
Insert(c, Int(*Pointer<Byte>(element + 1)), 1);
case FORMAT_R8UI:
Insert(c, Int(*Pointer<Byte>(element)), 0);
if(format != FORMAT_A8B8G8R8UI)
{
Insert(c, Int(0xFF), 3); // Set alpha
}
break;
case FORMAT_A16B16G16R16I:
Insert(c, Int(*Pointer<Short>(element + 3)), 3);
case FORMAT_X16B16G16R16I:
Insert(c, Int(*Pointer<Short>(element + 2)), 2);
case FORMAT_G16R16I:
Insert(c, Int(*Pointer<Short>(element + 1)), 1);
case FORMAT_R16I:
Insert(c, Int(*Pointer<Short>(element)), 0);
if(format != FORMAT_A16B16G16R16I)
{
Insert(c, Int(0x7FFF), 3); // Set alpha
}
break;
case FORMAT_A16B16G16R16UI:
Insert(c, Int(*Pointer<UShort>(element + 3)), 3);
case FORMAT_X16B16G16R16UI:
Insert(c, Int(*Pointer<UShort>(element + 2)), 2);
case FORMAT_G16R16UI:
Insert(c, Int(*Pointer<UShort>(element + 1)), 1);
case FORMAT_R16UI:
Insert(c, Int(*Pointer<UShort>(element)), 0);
if(format != FORMAT_A16B16G16R16UI)
{
Insert(c, Int(0xFFFF), 3); // Set alpha
}
break;
case FORMAT_A32B32G32R32I:
Insert(c, Int(*Pointer<Int>(element + 3)), 3);
case FORMAT_X32B32G32R32I:
Insert(c, Int(*Pointer<Int>(element + 2)), 2);
case FORMAT_G32R32I:
Insert(c, Int(*Pointer<Int>(element + 1)), 1);
case FORMAT_R32I:
Insert(c, Int(*Pointer<Int>(element)), 0);
if(format != FORMAT_A32B32G32R32I)
{
Insert(c, Int(0x7FFFFFFF), 3); // Set alpha
}
break;
case FORMAT_A32B32G32R32UI:
Insert(c, Int(*Pointer<UInt>(element + 3)), 3);
case FORMAT_X32B32G32R32UI:
Insert(c, Int(*Pointer<UInt>(element + 2)), 2);
case FORMAT_G32R32UI:
Insert(c, Int(*Pointer<UInt>(element + 1)), 1);
case FORMAT_R32UI:
Insert(c, Int(*Pointer<UInt>(element)), 0);
if(format != FORMAT_A32B32G32R32UI)
{
Insert(c, Int(UInt(0xFFFFFFFFU)), 3); // Set alpha
}
break;
default:
return false;
}
return true;
}
bool Blitter::write(Int4 &c, Pointer<Byte> element, Format format)
{
switch(format)
{
case FORMAT_A8B8G8R8I:
*Pointer<SByte>(element + 3) = As<SByte>(Extract(c, 3));
case FORMAT_X8B8G8R8I:
*Pointer<SByte>(element + 2) = As<SByte>(Extract(c, 2));
case FORMAT_G8R8I:
*Pointer<SByte>(element + 1) = As<SByte>(Extract(c, 1));
case FORMAT_R8I:
*Pointer<SByte>(element) = As<SByte>(Extract(c, 0));
if(format != FORMAT_A8B8G8R8I)
{
*Pointer<SByte>(element + 3) = SByte(0x7F);
}
break;
case FORMAT_A8B8G8R8UI:
*Pointer<Byte>(element + 3) = As<Byte>(Extract(c, 3));
case FORMAT_X8B8G8R8UI:
*Pointer<Byte>(element + 2) = As<Byte>(Extract(c, 2));
case FORMAT_G8R8UI:
*Pointer<Byte>(element + 1) = As<Byte>(Extract(c, 1));
case FORMAT_R8UI:
*Pointer<Byte>(element) = As<Byte>(Extract(c, 0));
if(format != FORMAT_A8B8G8R8UI)
{
*Pointer<Byte>(element + 3) = Byte(0xFF);
}
break;
case FORMAT_A16B16G16R16I:
*Pointer<Short>(element + 3) = As<Short>(Extract(c, 3));
case FORMAT_X16B16G16R16I:
*Pointer<Short>(element + 2) = As<Short>(Extract(c, 2));
case FORMAT_G16R16I:
*Pointer<Short>(element + 1) = As<Short>(Extract(c, 1));
case FORMAT_R16I:
*Pointer<Short>(element) = As<Short>(Extract(c, 0));
if(format != FORMAT_A16B16G16R16I)
{
*Pointer<Short>(element + 3) = Short(0x7FFF);
}
break;
case FORMAT_A16B16G16R16UI:
*Pointer<UShort>(element + 3) = As<UShort>(Extract(c, 3));
case FORMAT_X16B16G16R16UI:
*Pointer<UShort>(element + 2) = As<UShort>(Extract(c, 2));
case FORMAT_G16R16UI:
*Pointer<UShort>(element + 1) = As<UShort>(Extract(c, 1));
case FORMAT_R16UI:
*Pointer<UShort>(element) = As<UShort>(Extract(c, 0));
if(format != FORMAT_A16B16G16R16UI)
{
*Pointer<UShort>(element + 3) = UShort(0xFFFF);
}
break;
case FORMAT_A32B32G32R32I:
*Pointer<Int4>(element) = c;
break;
case FORMAT_X32B32G32R32I:
*Pointer<Int4>(element) = c;
*Pointer<Int>(element + 3) = Int(0x7FFFFFFF);
break;
case FORMAT_G32R32I:
*Pointer<Int2>(element) = As<Int2>(c);
break;
case FORMAT_R32I:
*Pointer<Int>(element) = Extract(c, 0);
break;
case FORMAT_A32B32G32R32UI:
*Pointer<UInt4>(element) = As<UInt4>(c);
break;
case FORMAT_X32B32G32R32UI:
*Pointer<UInt4>(element) = As<UInt4>(c);
*Pointer<UInt>(element + 3) = UInt(0xFFFFFFFF);
break;
case FORMAT_G32R32UI:
*Pointer<UInt2>(element) = As<UInt2>(c);
break;
case FORMAT_R32UI:
*Pointer<UInt>(element) = As<UInt>(Extract(c, 0));
break;
default:
return false;
}
return true;
}
bool Blitter::GetScale(float4& scale, Format format)
{
switch(format)
{
case FORMAT_L8:
case FORMAT_A8:
case FORMAT_A8R8G8B8:
case FORMAT_X8R8G8B8:
case FORMAT_R8:
case FORMAT_G8R8:
case FORMAT_X8B8G8R8:
case FORMAT_A8B8G8R8:
scale = vector(0xFF, 0xFF, 0xFF, 0xFF);
break;
case FORMAT_R8I_SNORM:
case FORMAT_G8R8I_SNORM:
case FORMAT_X8B8G8R8I_SNORM:
case FORMAT_A8B8G8R8I_SNORM:
scale = vector(0x7F, 0x7F, 0x7F, 0x7F);
break;
case FORMAT_R8I:
case FORMAT_R8UI:
case FORMAT_G8R8I:
case FORMAT_G8R8UI:
case FORMAT_X8B8G8R8I:
case FORMAT_X8B8G8R8UI:
case FORMAT_A8B8G8R8I:
case FORMAT_A8B8G8R8UI:
case FORMAT_R16I:
case FORMAT_R16UI:
case FORMAT_G16R16:
case FORMAT_G16R16I:
case FORMAT_G16R16UI:
case FORMAT_X16B16G16R16I:
case FORMAT_X16B16G16R16UI:
case FORMAT_A16B16G16R16:
case FORMAT_A16B16G16R16I:
case FORMAT_A16B16G16R16UI:
case FORMAT_R32I:
case FORMAT_R32UI:
case FORMAT_G32R32I:
case FORMAT_G32R32UI:
case FORMAT_X32B32G32R32I:
case FORMAT_X32B32G32R32UI:
case FORMAT_A32B32G32R32I:
case FORMAT_A32B32G32R32UI:
case FORMAT_A32B32G32R32F:
case FORMAT_G32R32F:
case FORMAT_R32F:
scale = vector(1.0f, 1.0f, 1.0f, 1.0f);
break;
default:
return false;
}
return true;
}
Routine *Blitter::generate(BlitState &state) Routine *Blitter::generate(BlitState &state)
{ {
Function<Void, Pointer<Byte> > function; Function<Void, Pointer<Byte> > function;
...@@ -205,9 +675,29 @@ namespace sw ...@@ -205,9 +675,29 @@ namespace sw
For(Int i = x0d, i < x1d, i++) For(Int i = x0d, i < x1d, i++)
{ {
bool intSrc = Surface::isNonNormalizedInteger(state.sourceFormat);
bool intDst = Surface::isNonNormalizedInteger(state.destFormat);
if(intSrc && intDst) // Integer types do not support filtering
{
Int4 color; // When both formats are true integer types, we don't go to float to avoid losing precision
Pointer<Byte> s = source + Int(y) * sPitchB + Int(x) * Surface::bytes(state.sourceFormat);
if(!read(color, s, state.sourceFormat))
{
return nullptr;
}
Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat);
if(!write(color, d, state.destFormat))
{
return nullptr;
}
}
else
{
Float4 color; Float4 color;
if(!state.filter) if(!state.filter || intSrc)
{ {
Int X = Int(x); Int X = Int(x);
Int Y = Int(y); Int Y = Int(y);
...@@ -249,53 +739,9 @@ namespace sw ...@@ -249,53 +739,9 @@ namespace sw
c11 * fx * fy; c11 * fx * fy;
} }
float4 unscale; float4 scale, unscale;
if(!GetScale(unscale, state.sourceFormat) || !GetScale(scale, state.destFormat))
switch(state.sourceFormat)
{ {
case FORMAT_L8:
case FORMAT_A8:
case FORMAT_A8R8G8B8:
case FORMAT_A8B8G8R8:
case FORMAT_X8R8G8B8:
case FORMAT_X8B8G8R8:
unscale = vector(255, 255, 255, 255);
break;
case FORMAT_A16B16G16R16:
case FORMAT_G16R16:
unscale = vector(65535, 65535, 65535, 65535);
break;
case FORMAT_A32B32G32R32F:
case FORMAT_G32R32F:
case FORMAT_R32F:
unscale = vector(1.0f, 1.0f, 1.0f, 1.0f);
break;
default:
return nullptr;
}
float4 scale;
switch(state.destFormat)
{
case FORMAT_L8:
case FORMAT_A8:
case FORMAT_A8R8G8B8:
case FORMAT_A8B8G8R8:
case FORMAT_X8R8G8B8:
case FORMAT_X8B8G8R8:
scale = vector(255, 255, 255, 255);
break;
case FORMAT_A16B16G16R16:
case FORMAT_G16R16:
scale = vector(65535, 65535, 65535, 65535);
break;
case FORMAT_A32B32G32R32F:
case FORMAT_G32R32F:
case FORMAT_R32F:
scale = vector(1.0f, 1.0f, 1.0f, 1.0f);
break;
default:
return nullptr; return nullptr;
} }
...@@ -316,60 +762,11 @@ namespace sw ...@@ -316,60 +762,11 @@ namespace sw
Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat); Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat);
switch(state.destFormat) if(!write(color, d, state.destFormat))
{ {
case FORMAT_L8:
*Pointer<Byte>(d) = Byte(RoundInt(Float(color.x)));
break;
case FORMAT_A8:
*Pointer<Byte>(d) = Byte(RoundInt(Float(color.w)));
break;
case FORMAT_A8R8G8B8:
{
UShort4 c0 = As<UShort4>(RoundShort4(color.zyxw));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(d) = UInt(As<Long>(c1));
}
break;
case FORMAT_A8B8G8R8:
{
UShort4 c0 = As<UShort4>(RoundShort4(color));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(d) = UInt(As<Long>(c1));
}
break;
case FORMAT_X8R8G8B8:
{
UShort4 c0 = As<UShort4>(RoundShort4(color.zyxw));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(d) = UInt(As<Long>(c1)) | 0xFF000000;
}
break;
case FORMAT_X8B8G8R8:
{
UShort4 c0 = As<UShort4>(RoundShort4(color));
Byte8 c1 = Pack(c0, c0);
*Pointer<UInt>(d) = UInt(As<Long>(c1)) | 0xFF000000;
}
break;
case FORMAT_A16B16G16R16:
*Pointer<UShort4>(d) = UShort4(RoundInt(color));
break;
case FORMAT_G16R16:
*Pointer<UInt>(d) = UInt(As<Long>(UShort4(RoundInt(color))));
break;
case FORMAT_A32B32G32R32F:
*Pointer<Float4>(d) = color;
break;
case FORMAT_G32R32F:
*Pointer<Float2>(d) = Float2(color);
break;
case FORMAT_R32F:
*Pointer<Float>(d) = color.x;
break;
default:
return nullptr; return nullptr;
} }
}
x += w; x += w;
} }
......
...@@ -65,6 +65,10 @@ namespace sw ...@@ -65,6 +65,10 @@ namespace sw
private: private:
bool read(Float4 &color, Pointer<Byte> element, Format format); bool read(Float4 &color, Pointer<Byte> element, Format format);
bool write(Float4 &color, Pointer<Byte> element, Format format);
bool read(Int4 &color, Pointer<Byte> element, Format format);
bool write(Int4 &color, Pointer<Byte> element, Format format);
static bool GetScale(float4& scale, Format format);
bool blitReactor(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter); bool blitReactor(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);
Routine *generate(BlitState &state); Routine *generate(BlitState &state);
......
...@@ -2290,11 +2290,30 @@ namespace sw ...@@ -2290,11 +2290,30 @@ namespace sw
{ {
case FORMAT_R5G6B5: case FORMAT_R5G6B5:
case FORMAT_X8R8G8B8: case FORMAT_X8R8G8B8:
case FORMAT_X8B8G8R8I:
case FORMAT_X8B8G8R8: case FORMAT_X8B8G8R8:
case FORMAT_A8R8G8B8: case FORMAT_A8R8G8B8:
case FORMAT_A8B8G8R8I:
case FORMAT_R8UI:
case FORMAT_G8R8UI:
case FORMAT_X8B8G8R8UI:
case FORMAT_A8B8G8R8UI:
case FORMAT_A8B8G8R8: case FORMAT_A8B8G8R8:
case FORMAT_G8R8I:
case FORMAT_G8R8: case FORMAT_G8R8:
case FORMAT_R8I_SNORM:
case FORMAT_G8R8I_SNORM:
case FORMAT_X8B8G8R8I_SNORM:
case FORMAT_A8B8G8R8I_SNORM:
case FORMAT_R16I:
case FORMAT_R16UI:
case FORMAT_G16R16I:
case FORMAT_G16R16UI:
case FORMAT_G16R16: case FORMAT_G16R16:
case FORMAT_X16B16G16R16I:
case FORMAT_X16B16G16R16UI:
case FORMAT_A16B16G16R16I:
case FORMAT_A16B16G16R16UI:
case FORMAT_A16B16G16R16: case FORMAT_A16B16G16R16:
case FORMAT_V8U8: case FORMAT_V8U8:
case FORMAT_Q8W8V8U8: case FORMAT_Q8W8V8U8:
...@@ -2303,6 +2322,7 @@ namespace sw ...@@ -2303,6 +2322,7 @@ namespace sw
case FORMAT_A16W16V16U16: case FORMAT_A16W16V16U16:
case FORMAT_Q16W16V16U16: case FORMAT_Q16W16V16U16:
case FORMAT_A8: case FORMAT_A8:
case FORMAT_R8I:
case FORMAT_R8: case FORMAT_R8:
case FORMAT_L8: case FORMAT_L8:
case FORMAT_L16: case FORMAT_L16:
...@@ -2310,6 +2330,14 @@ namespace sw ...@@ -2310,6 +2330,14 @@ namespace sw
case FORMAT_YV12_BT601: case FORMAT_YV12_BT601:
case FORMAT_YV12_BT709: case FORMAT_YV12_BT709:
case FORMAT_YV12_JFIF: case FORMAT_YV12_JFIF:
case FORMAT_R32I:
case FORMAT_R32UI:
case FORMAT_G32R32I:
case FORMAT_G32R32UI:
case FORMAT_X32B32G32R32I:
case FORMAT_X32B32G32R32UI:
case FORMAT_A32B32G32R32I:
case FORMAT_A32B32G32R32UI:
return false; return false;
case FORMAT_R32F: case FORMAT_R32F:
case FORMAT_G32R32F: case FORMAT_G32R32F:
...@@ -2512,6 +2540,40 @@ namespace sw ...@@ -2512,6 +2540,40 @@ namespace sw
} }
} }
bool Surface::isNonNormalizedInteger(Format format)
{
switch(format)
{
case FORMAT_A8B8G8R8I:
case FORMAT_X8B8G8R8I:
case FORMAT_G8R8I:
case FORMAT_R8I:
case FORMAT_A8B8G8R8UI:
case FORMAT_X8B8G8R8UI:
case FORMAT_G8R8UI:
case FORMAT_R8UI:
case FORMAT_A16B16G16R16I:
case FORMAT_X16B16G16R16I:
case FORMAT_G16R16I:
case FORMAT_R16I:
case FORMAT_A16B16G16R16UI:
case FORMAT_X16B16G16R16UI:
case FORMAT_G16R16UI:
case FORMAT_R16UI:
case FORMAT_A32B32G32R32I:
case FORMAT_X32B32G32R32I:
case FORMAT_G32R32I:
case FORMAT_R32I:
case FORMAT_A32B32G32R32UI:
case FORMAT_X32B32G32R32UI:
case FORMAT_G32R32UI:
case FORMAT_R32UI:
return true;
default:
return false;
}
}
int Surface::componentCount(Format format) int Surface::componentCount(Format format)
{ {
switch(format) switch(format)
...@@ -3300,46 +3362,40 @@ namespace sw ...@@ -3300,46 +3362,40 @@ namespace sw
external.write(x, y, color); external.write(x, y, color);
} }
Color<float> Surface::readInternal(int x, int y, int z) const void Surface::copyInternal(const Surface* source, int x, int y, float srcX, float srcY, bool filter)
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
return internal.read(x, y, z); sw::Color<float> color;
}
Color<float> Surface::readInternal(int x, int y) const if(!filter)
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); color = source->internal.read((int)srcX, (int)srcY);
return internal.read(x, y);
} }
else // Bilinear filtering
Color<float> Surface::sampleInternal(float x, float y, float z) const
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); color = source->internal.sample(srcX, srcY);
}
return internal.sample(x, y, z); internal.write(x, y, color);
} }
Color<float> Surface::sampleInternal(float x, float y) const void Surface::copyInternal(const Surface* source, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter)
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
return internal.sample(x, y); sw::Color<float> color;
}
void Surface::writeInternal(int x, int y, int z, const Color<float> &color) if(!filter)
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); color = source->internal.read((int)srcX, (int)srcY, int(srcZ));
internal.write(x, y, z, color);
} }
else // Bilinear filtering
void Surface::writeInternal(int x, int y, const Color<float> &color)
{ {
ASSERT(internal.lock != LOCK_UNLOCKED); color = source->internal.sample(srcX, srcY, srcZ);
}
internal.write(x, y, color); internal.write(x, y, z, color);
} }
bool Surface::hasStencil() const bool Surface::hasStencil() const
......
...@@ -294,12 +294,8 @@ namespace sw ...@@ -294,12 +294,8 @@ namespace sw
void writeExternal(int x, int y, int z, const Color<float> &color); void writeExternal(int x, int y, int z, const Color<float> &color);
void writeExternal(int x, int y, const Color<float> &color); void writeExternal(int x, int y, const Color<float> &color);
Color<float> readInternal(int x, int y, int z) const; void copyInternal(const Surface* src, int x, int y, float srcX, float srcY, bool filter);
Color<float> readInternal(int x, int y) const; void copyInternal(const Surface* src, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter);
Color<float> sampleInternal(float x, float y, float z) const;
Color<float> sampleInternal(float x, float y) const;
void writeInternal(int x, int y, int z, const Color<float> &color);
void writeInternal(int x, int y, const Color<float> &color);
bool hasStencil() const; bool hasStencil() const;
bool hasDepth() const; bool hasDepth() const;
...@@ -327,6 +323,7 @@ namespace sw ...@@ -327,6 +323,7 @@ namespace sw
static bool isSRGBreadable(Format format); static bool isSRGBreadable(Format format);
static bool isSRGBwritable(Format format); static bool isSRGBwritable(Format format);
static bool isCompressed(Format format); static bool isCompressed(Format format);
static bool isNonNormalizedInteger(Format format);
static int componentCount(Format format); static int componentCount(Format format);
static void setTexturePalette(unsigned int *palette); static void setTexturePalette(unsigned int *palette);
......
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