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, ...@@ -3235,99 +3235,69 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
// buffer, the depth buffer, and / or the stencil buffer depending on mask." // 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 // 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. // by internally scaling the read and draw rectangles.
// Remove reversal from readRect to simplify further operations.
gl::Rectangle readRect = readRectIn; gl::Rectangle readRect = readRectIn;
gl::Rectangle drawRect = drawRectIn; gl::Rectangle drawRect = drawRectIn;
if (readRect.isReversedX())
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)
{ {
int delta = readRect.y - readSize.height; readRect.x = readRect.x + readRect.width;
readRect.y -= delta; readRect.width = -readRect.width;
readRect.height += delta; drawRect.x = drawRect.x + drawRect.width;
drawRect.width = -drawRect.width;
int drawDelta = delta * flip(drawRect.height);
drawRect.y += drawDelta;
drawRect.height -= drawDelta;
} }
if (readRect.isReversedY())
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)
{ {
int readOffset = -readRect.x; readRect.y = readRect.y + readRect.height;
readRect.x += readOffset; readRect.height = -readRect.height;
readRect.width -= readOffset; drawRect.y = drawRect.y + drawRect.height;
drawRect.height = -drawRect.height;
int drawOffset = readToDrawX(readOffset);
drawRect.x += drawOffset;
drawRect.width -= drawOffset;
} }
auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) { gl::Rectangle readBounds(0, 0, readSize.width, readSize.height);
double readToDrawScale = gl::Rectangle inBoundsReadRect;
static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height); if (!gl::ClipRectangle(readRect, readBounds, &inBoundsReadRect))
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
};
if (readRect.y < 0)
{ {
int readOffset = -readRect.y; return gl::NoError();
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;
} }
if (readRect.y1() < 0)
{ {
int readOffset = -readRect.y1(); // Calculate the drawRect that corresponds to inBoundsReadRect.
readRect.height += readOffset; auto readToDrawX = [&drawRect, &readRect](int readOffset) {
double readToDrawScale =
int drawOffset = readToDrawY(readOffset); static_cast<double>(drawRect.width) / static_cast<double>(readRect.width);
drawRect.height += drawOffset; 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) gl::Rectangle drawRectMatchingInBoundsReadRect;
{ drawRectMatchingInBoundsReadRect.x = readToDrawX(inBoundsReadRect.x);
int delta = readRect.x1() - readSize.width; drawRectMatchingInBoundsReadRect.y = readToDrawY(inBoundsReadRect.y);
readRect.width -= delta; drawRectMatchingInBoundsReadRect.width =
drawRect.width -= delta * flip(drawRect.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; gl::Rectangle scissoredDrawRect;
readRect.height -= delta; if (!gl::ClipRectangle(drawRect, *scissor, &scissoredDrawRect))
drawRect.height -= delta * flip(drawRect.height); {
return gl::NoError();
}
scissorNeeded = scissoredDrawRect != drawRect;
} }
bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
const auto &destFormatInfo = const auto &destFormatInfo =
gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat()); gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
const auto &srcFormatInfo = const auto &srcFormatInfo =
...@@ -3360,8 +3330,8 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context, ...@@ -3360,8 +3330,8 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
bool flipRequired = ASSERT(!readRect.isReversedX() && !readRect.isReversedY());
readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; bool reversalRequired = drawRect.isReversedX() || drawRect.isReversedY();
bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
readRect.y < 0 || readRect.y + readRect.height > readSize.height || readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
...@@ -3373,7 +3343,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context, ...@@ -3373,7 +3343,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
if (readRenderTarget11->getFormatSet().formatID == if (readRenderTarget11->getFormatSet().formatID ==
drawRenderTarget11->getFormatSet().formatID && drawRenderTarget11->getFormatSet().formatID &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && !stretchRequired && !outOfBounds && !reversalRequired && !partialDSBlit &&
!colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
{ {
UINT dstX = drawRect.x; UINT dstX = drawRect.x;
......
...@@ -1272,10 +1272,6 @@ TEST_P(BlitFramebufferTest, PartialBlitSRGBToRGB) ...@@ -1272,10 +1272,6 @@ TEST_P(BlitFramebufferTest, PartialBlitSRGBToRGB)
// clipped out). // clipped out).
TEST_P(BlitFramebufferTest, BlitSRGBToRGBOversizedSourceArea) 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 kWidth = 256;
constexpr const GLsizei kHeight = 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