Commit b9dda64e by Alexis Hetu Committed by Alexis Hétu

glBlitFramebuffer support for depth/stencil formats

Added support for depth and stencil formats for glBlitFramebuffer: - Blitter now supports quad layout and stencil - Device::stretchRect() now supports specific buffers, so that a caller can specifically choose which buffer to copy Change-Id: Iae0898df11e0a1d3c006113486ed15a3fd2f90a9 Reviewed-on: https://swiftshader-review.googlesource.com/7510Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent a6e99c02
......@@ -3873,7 +3873,7 @@ void Context::setVertexAttrib(GLuint index, const GLuint *values)
void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, bool filter)
GLbitfield mask, bool filter, bool allowPartialDepthStencilBlit)
{
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
......@@ -4048,7 +4048,8 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
bool blitRenderTarget = false;
bool blitDepthStencil = false;
bool blitDepth = false;
bool blitStencil = false;
if(mask & GL_COLOR_BUFFER_BIT)
{
......@@ -4083,7 +4084,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
return error(GL_INVALID_OPERATION);
}
blitDepthStencil = true;
blitDepth = true;
readDSBuffer = readFramebuffer->getDepthbuffer();
drawDSBuffer = drawFramebuffer->getDepthbuffer();
}
......@@ -4098,15 +4099,15 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
return error(GL_INVALID_OPERATION);
}
blitDepthStencil = true;
blitStencil = true;
readDSBuffer = readFramebuffer->getStencilbuffer();
drawDSBuffer = drawFramebuffer->getStencilbuffer();
}
}
if(partialBufferCopy)
if(partialBufferCopy && !allowPartialDepthStencilBlit)
{
ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
ERR("Only whole-buffer depth and stencil blits are supported by ANGLE_framebuffer_blit.");
return error(GL_INVALID_OPERATION); // Only whole-buffer copies are permitted
}
......@@ -4117,7 +4118,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
}
if(blitRenderTarget || blitDepthStencil)
if(blitRenderTarget || blitDepth || blitStencil)
{
if(blitRenderTarget)
{
......@@ -4133,7 +4134,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
swap(destRect.y0, destRect.y1);
}
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, filter);
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::COLOR_BUFFER);
readRenderTarget->release();
drawRenderTarget->release();
......@@ -4145,9 +4146,32 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
}
if(blitDepthStencil)
if(blitDepth)
{
bool success = device->stretchRect(readFramebuffer->getDepthBuffer(), nullptr, drawFramebuffer->getDepthBuffer(), nullptr, false);
egl::Image *readRenderTarget = readFramebuffer->getDepthBuffer();
egl::Image *drawRenderTarget = drawFramebuffer->getDepthBuffer();
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::DEPTH_BUFFER);
readRenderTarget->release();
drawRenderTarget->release();
if(!success)
{
ERR("BlitFramebuffer failed.");
return;
}
}
if(blitStencil)
{
egl::Image *readRenderTarget = readFramebuffer->getStencilBuffer();
egl::Image *drawRenderTarget = drawFramebuffer->getStencilBuffer();
bool success = device->stretchRect(readRenderTarget, &sourceRect, drawRenderTarget, &destRect, (filter ? Device::USE_FILTER : 0) | Device::STENCIL_BUFFER);
readRenderTarget->release();
drawRenderTarget->release();
if(!success)
{
......
......@@ -684,7 +684,7 @@ public:
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, bool filter);
GLbitfield mask, bool filter, bool allowPartialDepthStencilBlit);
virtual void bindTexImage(egl::Surface *surface);
virtual EGLenum validateSharedImage(EGLenum target, GLuint name, GLuint textureLevel);
......
......@@ -510,7 +510,7 @@ namespace es2
}
}
bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, bool filter)
bool Device::stretchRect(sw::Surface *source, const sw::SliceRect *sourceRect, sw::Surface *dest, const sw::SliceRect *destRect, unsigned char flags)
{
if(!source || !dest)
{
......@@ -596,7 +596,12 @@ namespace es2
bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
bool depthStencil = egl::Image::isDepth(source->getInternalFormat()) || egl::Image::isStencil(source->getInternalFormat());
bool hasQuadLayout = Surface::hasQuadLayout(source->getInternalFormat()) || Surface::hasQuadLayout(dest->getInternalFormat());
bool fullCopy = (sRect.x0 == 0) && (sRect.y0 == 0) && (dRect.x0 == 0) && (dRect.y0 == 0) &&
(sRect.x1 == sWidth) && (sRect.y1 == sHeight) && (dRect.x1 == dWidth) && (dRect.y0 == 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;
if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||
......@@ -606,31 +611,31 @@ namespace es2
alpha0xFF = true;
}
if(depthStencil) // Copy entirely, internally // FIXME: Check
if((isDepth || isStencil) && !scaling && equalFormats && (!hasQuadLayout || fullCopy))
{
if(source->hasDepth())
if(source->hasDepth() && isDepth)
{
sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(0, 0, sourceRect->slice, LOCK_READONLY, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockInternal(0, 0, destRect->slice, LOCK_DISCARD, PUBLIC);
sw::byte *sourceBuffer = (sw::byte*)source->lockInternal(sRect.x0, sRect.y0, 0, LOCK_READONLY, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockInternal(dRect.x0, dRect.y0, 0, LOCK_DISCARD, PUBLIC);
copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
copyBuffer(sourceBuffer, destBuffer, dRect.width(), dRect.height(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
source->unlockInternal();
dest->unlockInternal();
}
if(source->hasStencil())
if(source->hasStencil() && isStencil)
{
sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(0, 0, 0, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockStencil(0, 0, 0, PUBLIC);
sw::byte *sourceBuffer = (sw::byte*)source->lockStencil(sRect.x0, sRect.y0, 0, PUBLIC);
sw::byte *destBuffer = (sw::byte*)dest->lockStencil(dRect.x0, dRect.y0, 0, PUBLIC);
copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getInternalPitchB(), dest->getInternalPitchB(), egl::Image::bytes(source->getInternalFormat()), flipX, flipY);
copyBuffer(sourceBuffer, destBuffer, source->getWidth(), source->getHeight(), source->getStencilPitchB(), dest->getStencilPitchB(), egl::Image::bytes(source->getStencilFormat()), flipX, flipY);
source->unlockStencil();
dest->unlockStencil();
}
}
else if(!scaling && equalFormats)
else if((flags & Device::COLOR_BUFFER) && !scaling && equalFormats && (!hasQuadLayout || fullCopy))
{
unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, sourceRect->slice, LOCK_READONLY, PUBLIC);
unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, destRect->slice, LOCK_READWRITE, PUBLIC);
......@@ -656,7 +661,7 @@ namespace es2
source->unlockInternal();
dest->unlockInternal();
}
else
else if(isColor || isDepth || isStencil)
{
if(flipX)
{
......@@ -666,7 +671,11 @@ namespace es2
{
swap(dRect.y0, dRect.y1);
}
blit(source, sRect, dest, dRect, scaling && filter);
blit(source, sRect, dest, dRect, scaling && (flags & Device::USE_FILTER), isStencil);
}
else
{
UNREACHABLE(false);
}
return true;
......
......@@ -39,6 +39,15 @@ namespace es2
class Device : public sw::Renderer
{
public:
enum : unsigned char
{
USE_FILTER = 0x01,
COLOR_BUFFER = 0x02,
DEPTH_BUFFER = 0x04,
STENCIL_BUFFER = 0x08,
ALL_BUFFERS = COLOR_BUFFER | DEPTH_BUFFER | STENCIL_BUFFER,
};
explicit Device(sw::Context *context);
virtual ~Device();
......@@ -64,7 +73,7 @@ namespace es2
void setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count);
void setViewport(const Viewport &viewport);
bool stretchRect(sw::Surface *sourceSurface, const sw::SliceRect *sourceRect, sw::Surface *destSurface, const sw::SliceRect *destRect, bool filter);
bool stretchRect(sw::Surface *sourceSurface, const sw::SliceRect *sourceRect, sw::Surface *destSurface, const sw::SliceRect *destRect, unsigned char flags);
bool stretchCube(sw::Surface *sourceSurface, sw::Surface *destSurface);
void finish();
......
......@@ -480,7 +480,7 @@ bool Texture::copy(egl::Image *source, const sw::SliceRect &sourceRect, GLenum d
Device *device = getDevice();
sw::SliceRect destRect(xoffset, yoffset, xoffset + (sourceRect.x1 - sourceRect.x0), yoffset + (sourceRect.y1 - sourceRect.y0), zoffset);
bool success = device->stretchRect(source, &sourceRect, dest, &destRect, false);
bool success = device->stretchRect(source, &sourceRect, dest, &destRect, Device::ALL_BUFFERS);
if(!success)
{
......@@ -926,7 +926,7 @@ void Texture2D::generateMipmaps()
return error(GL_OUT_OF_MEMORY);
}
getDevice()->stretchRect(image[i - 1], 0, image[i], 0, true);
getDevice()->stretchRect(image[i - 1], 0, image[i], 0, Device::ALL_BUFFERS | Device::USE_FILTER);
}
}
......@@ -1415,7 +1415,7 @@ void TextureCubeMap::generateMipmaps()
return error(GL_OUT_OF_MEMORY);
}
getDevice()->stretchRect(image[f][i - 1], 0, image[f][i], 0, true);
getDevice()->stretchRect(image[f][i - 1], 0, image[f][i], 0, Device::ALL_BUFFERS | Device::USE_FILTER);
}
}
}
......@@ -2001,7 +2001,7 @@ void Texture2DArray::generateMipmaps()
{
sw::SliceRect srcRect(0, 0, srcw, srch, z);
sw::SliceRect dstRect(0, 0, w, h, z);
getDevice()->stretchRect(image[i - 1], &srcRect, image[i], &dstRect, true);
getDevice()->stretchRect(image[i - 1], &srcRect, image[i], &dstRect, Device::ALL_BUFFERS | Device::USE_FILTER);
}
}
}
......
......@@ -6236,7 +6236,7 @@ void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
}
}
void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
static void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, bool allowPartialDepthStencilBlit)
{
TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
"GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
......@@ -6266,10 +6266,15 @@ void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint
return error(GL_INVALID_OPERATION);
}
context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false);
context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
}
}
void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
}
void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
......@@ -6279,7 +6284,7 @@ void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GL
return error(GL_INVALID_OPERATION);
}
glBlitFramebufferNV(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
}
void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
......
......@@ -1447,7 +1447,7 @@ GL_APICALL void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint sr
return error(GL_INVALID_OPERATION);
}
context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter == GL_LINEAR);
context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter == GL_LINEAR, true);
}
}
......
......@@ -40,9 +40,17 @@ namespace sw
blit(&color, sRect, dest, dRect, clearOptions);
}
void Blitter::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
void Blitter::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil)
{
Blitter::Options options = filter ? static_cast<Blitter::Options>(WRITE_RGBA | FILTER_LINEAR) : WRITE_RGBA;
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);
}
......@@ -321,6 +329,9 @@ namespace sw
case FORMAT_D32FS8_SHADOW:
c.x = *Pointer<Float>(element);
break;
case FORMAT_S8:
c.x = Float(Int(*Pointer<Byte>(element)));
break;
default:
return false;
}
......@@ -689,6 +700,9 @@ namespace sw
case FORMAT_D32FS8_SHADOW:
*Pointer<Float>(element) = c.x;
break;
case FORMAT_S8:
*Pointer<Byte>(element) = Byte(RoundInt(Float(c.x)));
break;
default:
return false;
}
......@@ -978,7 +992,8 @@ namespace sw
case FORMAT_D32F_LOCKABLE:
case FORMAT_D32FS8_TEXTURE:
case FORMAT_D32FS8_SHADOW:
scale = vector(1.0f, 0.0f, 0.0f, 0.0f);
case FORMAT_S8:
scale = vector(1.0f, 1.0f, 1.0f, 1.0f);
break;
default:
return false;
......@@ -1036,6 +1051,12 @@ namespace sw
return true;
}
Int Blitter::ComputeOffset(Int& x, Int& y, Int& pitchB, int bytes, bool quadLayout)
{
return (quadLayout ? (y & Int(~1)) : y) * pitchB +
(quadLayout ? ((y & Int(1)) << 1) + (x * 2) - (x & Int(1)) : x) * bytes;
}
Routine *Blitter::generate(BlitState &state)
{
Function<Void(Pointer<Byte>)> function;
......@@ -1063,6 +1084,10 @@ namespace sw
bool intSrc = Surface::isNonNormalizedInteger(state.sourceFormat);
bool intDst = Surface::isNonNormalizedInteger(state.destFormat);
bool intBoth = intSrc && intDst;
bool srcQuadLayout = Surface::hasQuadLayout(state.sourceFormat);
bool dstQuadLayout = Surface::hasQuadLayout(state.destFormat);
int srcBytes = Surface::bytes(state.sourceFormat);
int dstBytes = Surface::bytes(state.destFormat);
bool hasConstantColorI = false;
Int4 constantColorI;
......@@ -1098,11 +1123,11 @@ namespace sw
For(Int j = y0d, j < y1d, j++)
{
Float x = x0;
Pointer<Byte> destLine = dest + j * dPitchB;
Pointer<Byte> destLine = dest + (dstQuadLayout ? j & Int(~1) : j) * dPitchB;
For(Int i = x0d, i < x1d, i++)
{
Pointer<Byte> d = destLine + i * Surface::bytes(state.destFormat);
Pointer<Byte> d = destLine + (dstQuadLayout ? (((j & Int(1)) << 1) + (i * 2) - (i & Int(1))) : i) * dstBytes;
if(hasConstantColorI)
{
if(!write(constantColorI, d, state.destFormat, state.options))
......@@ -1120,7 +1145,11 @@ namespace sw
else if(intBoth) // 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);
Int X = Int(x);
Int Y = Int(y);
Pointer<Byte> s = source + ComputeOffset(X, Y, sPitchB, srcBytes, srcQuadLayout);
if(!read(color, s, state.sourceFormat))
{
return nullptr;
......@@ -1140,7 +1169,7 @@ namespace sw
Int X = Int(x);
Int Y = Int(y);
Pointer<Byte> s = source + Y * sPitchB + X * Surface::bytes(state.sourceFormat);
Pointer<Byte> s = source + ComputeOffset(X, Y, sPitchB, srcBytes, srcQuadLayout);
if(!read(color, s, state.sourceFormat))
{
......@@ -1158,10 +1187,10 @@ namespace sw
Int X1 = IfThenElse(X0 + 1 >= sWidth, X0, X0 + 1);
Int Y1 = IfThenElse(Y0 + 1 >= sHeight, Y0, Y0 + 1);
Pointer<Byte> s00 = source + Y0 * sPitchB + X0 * Surface::bytes(state.sourceFormat);
Pointer<Byte> s01 = source + Y0 * sPitchB + X1 * Surface::bytes(state.sourceFormat);
Pointer<Byte> s10 = source + Y1 * sPitchB + X0 * Surface::bytes(state.sourceFormat);
Pointer<Byte> s11 = source + Y1 * sPitchB + X1 * Surface::bytes(state.sourceFormat);
Pointer<Byte> s00 = source + ComputeOffset(X0, Y0, sPitchB, srcBytes, srcQuadLayout);
Pointer<Byte> s01 = source + ComputeOffset(X1, Y0, sPitchB, srcBytes, srcQuadLayout);
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;
......@@ -1214,9 +1243,10 @@ namespace sw
bool useSourceInternal = !source->isExternalDirty();
bool useDestInternal = !dest->isExternalDirty();
bool isStencil = ((options & USE_STENCIL) == USE_STENCIL);
state.sourceFormat = source->getFormat(useSourceInternal);
state.destFormat = dest->getFormat(useDestInternal);
state.sourceFormat = isStencil ? source->getStencilFormat() : source->getFormat(useSourceInternal);
state.destFormat = isStencil ? dest->getStencilFormat() : dest->getFormat(useDestInternal);
state.options = options;
criticalSection.lock();
......@@ -1244,10 +1274,12 @@ namespace sw
bool isRGBA = ((options & WRITE_RGBA) == WRITE_RGBA);
bool isEntireDest = dest->isEntire(destRect);
data.source = source->lock(0, 0, sourceRect.slice, sw::LOCK_READONLY, sw::PUBLIC, useSourceInternal);
data.dest = dest->lock(0, 0, destRect.slice, isRGBA ? (isEntireDest ? sw::LOCK_DISCARD : sw::LOCK_WRITEONLY) : sw::LOCK_READWRITE, sw::PUBLIC, useDestInternal);
data.sPitchB = source->getPitchB(useSourceInternal);
data.dPitchB = dest->getPitchB(useDestInternal);
data.source = isStencil ? source->lockStencil(0, 0, 0, sw::PUBLIC) :
source->lock(0, 0, sourceRect.slice, sw::LOCK_READONLY, sw::PUBLIC, useSourceInternal);
data.dest = isStencil ? dest->lockStencil(0, 0, 0, sw::PUBLIC) :
dest->lock(0, 0, destRect.slice, isRGBA ? (isEntireDest ? sw::LOCK_DISCARD : sw::LOCK_WRITEONLY) : sw::LOCK_READWRITE, sw::PUBLIC, useDestInternal);
data.sPitchB = isStencil ? source->getStencilPitchB() : source->getPitchB(useSourceInternal);
data.dPitchB = isStencil ? dest->getStencilPitchB() : dest->getPitchB(useDestInternal);
data.w = 1.0f / (dRect.x1 - dRect.x0) * (sRect.x1 - sRect.x0);
data.h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
......@@ -1264,8 +1296,16 @@ namespace sw
blitFunction(&data);
source->unlock(useSourceInternal);
dest->unlock(useDestInternal);
if(isStencil)
{
source->unlockStencil();
dest->unlockStencil();
}
else
{
source->unlock(useSourceInternal);
dest->unlock(useDestInternal);
}
return true;
}
......
......@@ -34,7 +34,8 @@ namespace sw
WRITE_ALPHA = 0x08,
WRITE_RGBA = WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA,
FILTER_LINEAR = 0x10,
CLEAR_OPERATION = 0x20
CLEAR_OPERATION = 0x20,
USE_STENCIL = 0x40,
};
struct BlitState
......@@ -76,7 +77,7 @@ namespace sw
virtual ~Blitter();
void clear(void* pixel, sw::Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask);
void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);
void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false);
void blit3D(Surface *source, Surface *dest);
private:
......@@ -86,6 +87,7 @@ namespace sw
bool write(Int4 &color, Pointer<Byte> element, Format format, const Blitter::Options& options);
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 SliceRect &sRect, Surface *dest, const SliceRect &dRect, const Blitter::Options& options);
bool blitReactor(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, const Blitter::Options& options);
Routine *generate(BlitState &state);
......
......@@ -972,9 +972,7 @@ namespace sw
{
state.depthTestActive = true;
state.depthCompareMode = context->depthCompareMode;
state.quadLayoutDepthBuffer = context->depthBuffer->getInternalFormat() != FORMAT_D32F_LOCKABLE &&
context->depthBuffer->getInternalFormat() != FORMAT_D32FS8_TEXTURE &&
context->depthBuffer->getInternalFormat() != FORMAT_D32FS8_SHADOW;
state.quadLayoutDepthBuffer = Surface::hasQuadLayout(context->depthBuffer->getInternalFormat());
}
state.occlusionEnabled = context->occlusionEnabled;
......
......@@ -207,9 +207,9 @@ namespace sw
blitter.clear(pixel, format, dest, dRect, rgbaMask);
}
void Renderer::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter)
void Renderer::blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil)
{
blitter.blit(source, sRect, dest, dRect, filter);
blitter.blit(source, sRect, dest, dRect, filter, isStencil);
}
void Renderer::blit3D(Surface *source, Surface *dest)
......
......@@ -322,7 +322,7 @@ namespace sw
void operator delete(void * mem);
void clear(void* pixel, Format format, Surface *dest, const SliceRect &dRect, unsigned int rgbaMask);
void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);
void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false);
void blit3D(Surface *source, Surface *dest);
void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
......
......@@ -2629,6 +2629,34 @@ namespace sw
}
}
bool Surface::hasQuadLayout(Format format)
{
switch(format)
{
case FORMAT_D32:
case FORMAT_D16:
case FORMAT_D24X8:
case FORMAT_D24S8:
case FORMAT_D24FS8:
case FORMAT_D32F:
case FORMAT_D32F_COMPLEMENTARY:
case FORMAT_DF24S8:
case FORMAT_DF16S8:
case FORMAT_INTZ:
case FORMAT_S8:
case FORMAT_A8G8R8B8Q:
case FORMAT_X8G8R8B8Q:
return true;
case FORMAT_D32F_LOCKABLE:
case FORMAT_D32FS8_TEXTURE:
case FORMAT_D32FS8_SHADOW:
default:
break;
}
return false;
}
bool Surface::isPalette(Format format)
{
switch(format)
......@@ -2686,6 +2714,7 @@ namespace sw
case FORMAT_A8:
case FORMAT_R8I:
case FORMAT_R8:
case FORMAT_S8:
case FORMAT_L8:
case FORMAT_L16:
case FORMAT_A8L8:
......
......@@ -327,6 +327,7 @@ namespace sw
static bool isStencil(Format format);
static bool isDepth(Format format);
static bool hasQuadLayout(Format format);
static bool isPalette(Format format);
static bool isFloatFormat(Format format);
......
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