Commit 7f72df96 by Nicolas Capens Committed by Nicolas Capens

Fix blitting of quad layout data.

The stencil buffer always has a quad layout, and can't be copied using copyBuffer() even when copying the full buffer, because it copies one row at a time (i.e. it assumes a linear layout). Likewise a depth buffer may optionally have a quad layout and copying the full buffer still doesn't allow using copyBuffer(). To keep maximum performance for the typical case of copying between equally sized buffers, a new code path it added to copy the entire slice in one memcpy() call. Change-Id: I77f60f66e5cdcd7cf0a73d03f3d3485809d7ebe6 Reviewed-on: https://swiftshader-review.googlesource.com/15008Tested-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 57e7cea7
...@@ -455,7 +455,7 @@ namespace es2 ...@@ -455,7 +455,7 @@ namespace es2
this->viewport = viewport; this->viewport = viewport;
} }
void Device::copyBuffer(sw::byte *sourceBuffer, sw::byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY) void Device::copyBuffer(byte *sourceBuffer, byte *destBuffer, unsigned int width, unsigned int height, unsigned int sourcePitch, unsigned int destPitch, unsigned int bytes, bool flipX, bool flipY)
{ {
if(flipX) if(flipX)
{ {
...@@ -464,8 +464,8 @@ namespace es2 ...@@ -464,8 +464,8 @@ namespace es2
sourceBuffer += (height - 1) * sourcePitch; sourceBuffer += (height - 1) * sourcePitch;
for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch) for(unsigned int y = 0; y < height; ++y, sourceBuffer -= sourcePitch, destBuffer += destPitch)
{ {
sw::byte *srcX = sourceBuffer + (width - 1) * bytes; byte *srcX = sourceBuffer + (width - 1) * bytes;
sw::byte *dstX = destBuffer; byte *dstX = destBuffer;
for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes) for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
{ {
memcpy(dstX, srcX, bytes); memcpy(dstX, srcX, bytes);
...@@ -476,8 +476,8 @@ namespace es2 ...@@ -476,8 +476,8 @@ namespace es2
{ {
for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch) for(unsigned int y = 0; y < height; ++y, sourceBuffer += sourcePitch, destBuffer += destPitch)
{ {
sw::byte *srcX = sourceBuffer + (width - 1) * bytes; byte *srcX = sourceBuffer + (width - 1) * bytes;
sw::byte *dstX = destBuffer; byte *dstX = destBuffer;
for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes) for(unsigned int x = 0; x < width; ++x, dstX += bytes, srcX -= bytes)
{ {
memcpy(dstX, srcX, bytes); memcpy(dstX, srcX, bytes);
...@@ -709,15 +709,28 @@ namespace es2 ...@@ -709,15 +709,28 @@ namespace es2
return false; return false;
} }
bool isDepth = (flags & Device::DEPTH_BUFFER) && Surface::isDepth(source->getInternalFormat());
bool isStencil = (flags & Device::STENCIL_BUFFER) && Surface::isStencil(source->getInternalFormat());
bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
if(!isColor && !isDepth && !isStencil)
{
return true;
}
int sourceSliceB = isStencil ? source->getStencilSliceB() : source->getInternalSliceB();
int destSliceB = isStencil ? dest->getStencilSliceB() : dest->getInternalSliceB();
int sourcePitchB = isStencil ? source->getStencilPitchB() : source->getInternalPitchB();
int destPitchB = isStencil ? dest->getStencilPitchB() : dest->getInternalPitchB();
bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height()); bool scaling = (sRect.width() != (float)dRect.width()) || (sRect.height() != (float)dRect.height());
bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat()); bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) && bool fullCopy = (sRect.x0 == 0.0f) && (sRect.y0 == 0.0f) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
(sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y0 == dHeight); (sRect.x1 == (float)sWidth) && (sRect.y1 == (float)sHeight) && (dRect.x1 == dWidth) && (dRect.y1 == dHeight);
bool isDepth = (flags & Device::DEPTH_BUFFER) && egl::Image::isDepth(source->getInternalFormat());
bool isStencil = (flags & Device::STENCIL_BUFFER) && (egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat()));
bool isColor = (flags & Device::COLOR_BUFFER) == Device::COLOR_BUFFER;
bool alpha0xFF = false; bool alpha0xFF = false;
bool equalSlice = sourceSliceB == destSliceB;
bool smallMargin = sourcePitchB <= source->getWidth() * Surface::bytes(source->getInternalFormat()) + 16;
if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) || if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
(source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8)) (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))
...@@ -726,50 +739,46 @@ namespace es2 ...@@ -726,50 +739,46 @@ namespace es2
alpha0xFF = true; alpha0xFF = true;
} }
if((isDepth || isStencil) && !scaling && equalFormats && (!hasQuadLayout || fullCopy)) if(fullCopy && !scaling && equalFormats && !alpha0xFF && equalSlice && smallMargin && !flipX && !flipY)
{ {
if(source->hasDepth() && isDepth) byte *sourceBuffer = isStencil ? (byte*)source->lockStencil(0, 0, 0, PUBLIC) : (byte*)source->lockInternal(0, 0, 0, LOCK_READONLY, PUBLIC);
{ byte *destBuffer = isStencil ? (byte*)dest->lockStencil(0, 0, 0, PUBLIC) : (byte*)dest->lockInternal(0, 0, 0, LOCK_DISCARD, PUBLIC);
sw::byte *sourceBuffer = (sw::byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, LOCK_DISCARD, PUBLIC);
copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY); memcpy(destBuffer, sourceBuffer, sourceSliceB);
source->unlockInternal(); isStencil ? source->unlockStencil() : source->unlockInternal();
dest->unlockInternal(); isStencil ? dest->unlockStencil() : dest->unlockInternal();
} }
else if(isDepth && !scaling && equalFormats && !hasQuadLayout)
if(source->hasStencil() && isStencil) {
{ byte *sourceBuffer = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, 0, LOCK_READONLY, PUBLIC);
sw::byte *sourceBuffer = (sw::byte*)source->lockStencil((int)sRect.x0, (int)sRect.y0, 0, PUBLIC); byte *destBuffer = (byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockStencil(dRect.x0, dRect.y0, 0, PUBLIC);
copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getStencilPitchB(), dest->getStencilPitchB(), egl::Image::bytes(source->getStencilFormat()), flipX, flipY); copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
source->unlockStencil(); source->unlockInternal();
dest->unlockStencil(); dest->unlockInternal();
}
} }
else if((flags & Device::COLOR_BUFFER) && !scaling && equalFormats && (!hasQuadLayout || fullCopy)) else if((flags & Device::COLOR_BUFFER) && !scaling && equalFormats && !hasQuadLayout)
{ {
unsigned char *sourceBytes = (unsigned char*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC); byte *sourceBytes = (byte*)source->lockInternal((int)sRect.x0, (int)sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, LOCK_READWRITE, PUBLIC); byte *destBytes = (byte*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, fullCopy ? LOCK_DISCARD : LOCK_WRITEONLY, PUBLIC);
unsigned int sourcePitch = source->getInternalPitchB();
unsigned int destPitch = dest->getInternalPitchB();
unsigned int width = dRect.x1 - dRect.x0; unsigned int width = dRect.x1 - dRect.x0;
unsigned int height = dRect.y1 - dRect.y0; unsigned int height = dRect.y1 - dRect.y0;
copyBuffer(sourceBytes, destBytes, width, height, sourcePitch, destPitch, egl::Image::bytes(source->getInternalFormat()), flipX, flipY); copyBuffer(sourceBytes, destBytes, width, height, sourcePitchB, destPitchB, Surface::bytes(source->getInternalFormat()), flipX, flipY);
if(alpha0xFF) if(alpha0xFF)
{ {
for(unsigned int y = 0; y < height; ++y, destBytes += destPitch) for(unsigned int y = 0; y < height; y++)
{ {
for(unsigned int x = 0; x < width; ++x) for(unsigned int x = 0; x < width; x++)
{ {
destBytes[4 * x + 3] = 0xFF; destBytes[4 * x + 3] = 0xFF;
} }
destBytes += destPitchB;
} }
} }
...@@ -790,17 +799,14 @@ namespace es2 ...@@ -790,17 +799,14 @@ namespace es2
SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice); SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, sRect.slice);
blit(source, sRectF, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil); blit(source, sRectF, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
} }
else else UNREACHABLE(false);
{
UNREACHABLE(false);
}
return true; return true;
} }
bool Device::stretchCube(sw::Surface *source, sw::Surface *dest) bool Device::stretchCube(sw::Surface *source, sw::Surface *dest)
{ {
if(!source || !dest || egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat())) if(!source || !dest || Surface::isDepth(source->getInternalFormat()) || Surface::isStencil(source->getInternalFormat()))
{ {
ERR("Invalid parameters"); ERR("Invalid parameters");
return false; return false;
...@@ -828,7 +834,7 @@ namespace es2 ...@@ -828,7 +834,7 @@ namespace es2
{ {
unsigned int sourcePitch = source->getInternalPitchB(); unsigned int sourcePitch = source->getInternalPitchB();
unsigned int destPitch = dest->getInternalPitchB(); unsigned int destPitch = dest->getInternalPitchB();
unsigned int bytes = dWidth * egl::Image::bytes(source->getInternalFormat()); unsigned int bytes = dWidth * Surface::bytes(source->getInternalFormat());
for(int z = 0; z < dDepth; ++z) for(int z = 0; z < dDepth; ++z)
{ {
......
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