Prevent floating-point error accumulation during blitting.
The numeric imprecision can accumulate quickly and cause visible
sampling errors.
Bug chromium:848238
Change-Id: Ie41c10a0462e5b5e5c3ed5f7329ece00dab3f7f9
Reviewed-on: https://swiftshader-review.googlesource.com/19148
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Common/Version.h b/src/Common/Version.h
index ea9a476..9a28e1b 100644
--- a/src/Common/Version.h
+++ b/src/Common/Version.h
@@ -15,7 +15,7 @@
#define MAJOR_VERSION 4
#define MINOR_VERSION 0
#define BUILD_VERSION 0
-#define BUILD_REVISION 5
+#define BUILD_REVISION 6
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index c77491c..17c7199 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -163,28 +163,26 @@
swap(sRect.y0, sRect.y1);
}
- source->lockInternal((int)sRect.x0, (int)sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
- dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
+ source->lockInternal(0, 0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
+ dest->lockInternal(0, 0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
float w = sRect.width() / dRect.width();
float h = sRect.height() / dRect.height();
- const float xStart = sRect.x0 + 0.5f * w;
- float y = sRect.y0 + 0.5f * h;
+ float xStart = sRect.x0 + (0.5f - dRect.x0) * w;
+ float yStart = sRect.y0 + (0.5f - dRect.y0) * h;
for(int j = dRect.y0; j < dRect.y1; j++)
{
- float x = xStart;
+ float y = yStart + j * h;
for(int i = dRect.x0; i < dRect.x1; i++)
{
+ float x = xStart + i * w;
+
// FIXME: Support RGBA mask
dest->copyInternal(source, i, j, x, y, options.filter);
-
- x += w;
}
-
- y += h;
}
source->unlockInternal();
@@ -200,21 +198,21 @@
float h = static_cast<float>(source->getHeight()) / static_cast<float>(dest->getHeight());
float d = static_cast<float>(source->getDepth()) / static_cast<float>(dest->getDepth());
- float z = 0.5f * d;
for(int k = 0; k < dest->getDepth(); k++)
{
- float y = 0.5f * h;
+ float z = (k + 0.5f) * d;
+
for(int j = 0; j < dest->getHeight(); j++)
{
- float x = 0.5f * w;
+ float y = (j + 0.5f) * h;
+
for(int i = 0; i < dest->getWidth(); i++)
{
+ float x = (i + 0.5f) * w;
+
dest->copyInternal(source, i, j, k, x, y, z, true);
- x += w;
}
- y += h;
}
- z += d;
}
source->unlockInternal();
@@ -1237,15 +1235,14 @@
}
}
- Float y = y0;
-
For(Int j = y0d, j < y1d, j++)
{
- Float x = x0;
+ Float y = state.clearOperation ? y0 : y0 + Float(j) * h;
Pointer<Byte> destLine = dest + (dstQuadLayout ? j & Int(~1) : RValue<Int>(j)) * dPitchB;
For(Int i = x0d, i < x1d, i++)
{
+ Float x = state.clearOperation ? x0 : x0 + Float(i) * w;
Pointer<Byte> d = destLine + (dstQuadLayout ? (((j & Int(1)) << 1) + (i * 2) - (i & Int(1))) : RValue<Int>(i)) * dstBytes;
if(hasConstantColorI)
@@ -1379,11 +1376,7 @@
d += *Pointer<Int>(blit + OFFSET(BlitData,dSliceB));
}
}
-
- if(!state.clearOperation) { x += w; }
}
-
- if(!state.clearOperation) { y += h; }
}
}
@@ -1456,8 +1449,8 @@
data.w = sRect.width() / dRect.width();
data.h = sRect.height() / dRect.height();
- data.x0 = sRect.x0 + 0.5f * data.w;
- data.y0 = sRect.y0 + 0.5f * data.h;
+ data.x0 = sRect.x0 + (0.5f - dRect.x0) * data.w;
+ data.y0 = sRect.y0 + (0.5f - dRect.y0) * data.h;
data.x0d = dRect.x0;
data.x1d = dRect.x1;