Commit d7b56642 by Olli Etuaho Committed by Commit Bot

Fix blit rect calculations on D3D11 backend

The D3D11 backend used to calculate the blit areas incorrectly when the source blit area provided via the API stretched outside the source framebuffer in all directions. This is now fixed and the code is also simplified. BUG=angleproject:2521 TEST=angle_end2end_tests Change-Id: I46d5de27464a8455b3956c0be598f75550ca1616 Reviewed-on: https://chromium-review.googlesource.com/1032787Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent aae572a5
......@@ -3235,99 +3235,69 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
// buffer, the depth buffer, and / or the stencil buffer depending on mask."
// This means negative x and y are out of bounds, and not to be read from. We handle this here
// by internally scaling the read and draw rectangles.
// Remove reversal from readRect to simplify further operations.
gl::Rectangle readRect = readRectIn;
gl::Rectangle drawRect = drawRectIn;
auto flip = [](int val) { return val >= 0 ? 1 : -1; };
if (readRect.x > readSize.width && readRect.width < 0)
{
int delta = readRect.x - readSize.width;
readRect.x -= delta;
readRect.width += delta;
int drawDelta = delta * flip(drawRect.width);
drawRect.x += drawDelta;
drawRect.width -= drawDelta;
}
if (readRect.y > readSize.height && readRect.height < 0)
if (readRect.isReversedX())
{
int delta = readRect.y - readSize.height;
readRect.y -= delta;
readRect.height += delta;
int drawDelta = delta * flip(drawRect.height);
drawRect.y += drawDelta;
drawRect.height -= drawDelta;
readRect.x = readRect.x + readRect.width;
readRect.width = -readRect.width;
drawRect.x = drawRect.x + drawRect.width;
drawRect.width = -drawRect.width;
}
auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
};
if (readRect.x < 0)
if (readRect.isReversedY())
{
int readOffset = -readRect.x;
readRect.x += readOffset;
readRect.width -= readOffset;
int drawOffset = readToDrawX(readOffset);
drawRect.x += drawOffset;
drawRect.width -= drawOffset;
readRect.y = readRect.y + readRect.height;
readRect.height = -readRect.height;
drawRect.y = drawRect.y + drawRect.height;
drawRect.height = -drawRect.height;
}
auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
};
if (readRect.y < 0)
gl::Rectangle readBounds(0, 0, readSize.width, readSize.height);
gl::Rectangle inBoundsReadRect;
if (!gl::ClipRectangle(readRect, readBounds, &inBoundsReadRect))
{
int readOffset = -readRect.y;
readRect.y += readOffset;
readRect.height -= readOffset;
int drawOffset = readToDrawY(readOffset);
drawRect.y += drawOffset;
drawRect.height -= drawOffset;
}
if (readRect.x1() < 0)
{
int readOffset = -readRect.x1();
readRect.width += readOffset;
int drawOffset = readToDrawX(readOffset);
drawRect.width += drawOffset;
return gl::NoError();
}
if (readRect.y1() < 0)
{
int readOffset = -readRect.y1();
readRect.height += readOffset;
int drawOffset = readToDrawY(readOffset);
drawRect.height += drawOffset;
}
// Calculate the drawRect that corresponds to inBoundsReadRect.
auto readToDrawX = [&drawRect, &readRect](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRect.width) / static_cast<double>(readRect.width);
return static_cast<int>(
round(static_cast<double>(readOffset - readRect.x) * readToDrawScale) + drawRect.x);
};
auto readToDrawY = [&drawRect, &readRect](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRect.height) / static_cast<double>(readRect.height);
return static_cast<int>(
round(static_cast<double>(readOffset - readRect.y) * readToDrawScale) + drawRect.y);
};
if (readRect.x1() > readSize.width)
{
int delta = readRect.x1() - readSize.width;
readRect.width -= delta;
drawRect.width -= delta * flip(drawRect.width);
gl::Rectangle drawRectMatchingInBoundsReadRect;
drawRectMatchingInBoundsReadRect.x = readToDrawX(inBoundsReadRect.x);
drawRectMatchingInBoundsReadRect.y = readToDrawY(inBoundsReadRect.y);
drawRectMatchingInBoundsReadRect.width =
readToDrawX(inBoundsReadRect.x1()) - drawRectMatchingInBoundsReadRect.x;
drawRectMatchingInBoundsReadRect.height =
readToDrawY(inBoundsReadRect.y1()) - drawRectMatchingInBoundsReadRect.y;
drawRect = drawRectMatchingInBoundsReadRect;
readRect = inBoundsReadRect;
}
if (readRect.y1() > readSize.height)
bool scissorNeeded = false;
if (scissor)
{
int delta = readRect.y1() - readSize.height;
readRect.height -= delta;
drawRect.height -= delta * flip(drawRect.height);
gl::Rectangle scissoredDrawRect;
if (!gl::ClipRectangle(drawRect, *scissor, &scissoredDrawRect))
{
return gl::NoError();
}
scissorNeeded = scissoredDrawRect != drawRect;
}
bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
const auto &destFormatInfo =
gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
const auto &srcFormatInfo =
......@@ -3360,8 +3330,8 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
bool flipRequired =
readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
ASSERT(!readRect.isReversedX() && !readRect.isReversedY());
bool reversalRequired = drawRect.isReversedX() || drawRect.isReversedY();
bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
......@@ -3373,7 +3343,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
if (readRenderTarget11->getFormatSet().formatID ==
drawRenderTarget11->getFormatSet().formatID &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
!stretchRequired && !outOfBounds && !reversalRequired && !partialDSBlit &&
!colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
{
UINT dstX = drawRect.x;
......
......@@ -1272,10 +1272,6 @@ TEST_P(BlitFramebufferTest, PartialBlitSRGBToRGB)
// clipped out).
TEST_P(BlitFramebufferTest, BlitSRGBToRGBOversizedSourceArea)
{
// D3D11 blit implementation seems to have a bug where the blit rectangles are computed
// incorrectly. http://anglebug.com/2521
ANGLE_SKIP_TEST_IF(IsD3D11());
constexpr const GLsizei kWidth = 256;
constexpr const GLsizei kHeight = 256;
......
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