From 289138f01c35c14b669b55542eaf2e5f004ab9fc Mon Sep 17 00:00:00 2001 From: Pedro Pontes Date: Tue, 27 Apr 2021 14:13:58 +0200 Subject: [PATCH] chore: cherry-pick ed5f62c36d from angle. --- patches/angle/.patches | 1 + ...ere_is_no_intersection_of_dest_areas.patch | 137 ++++++++++++++++++ patches/config.json | 4 +- 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 patches/angle/.patches create mode 100644 patches/angle/d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch diff --git a/patches/angle/.patches b/patches/angle/.patches new file mode 100644 index 0000000000000..82ed05bacaf4f --- /dev/null +++ b/patches/angle/.patches @@ -0,0 +1 @@ +d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch diff --git a/patches/angle/d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch b/patches/angle/d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch new file mode 100644 index 0000000000000..a33a90fdd6001 --- /dev/null +++ b/patches/angle/d3d11_skip_blits_if_there_is_no_intersection_of_dest_areas.patch @@ -0,0 +1,137 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Geoff Lang +Date: Mon, 19 Apr 2021 12:47:05 -0400 +Subject: D3D11: Skip blits if there is no intersection of dest areas + +Blit11 would clip the destination rectangle with the destination size +but ignore the result. gl::ClipRectangle returns false when the +rectangles do not intersect at all, indicating the blit can be skipped. + +This could lead to an out-of-bounds write to the GPU memory for the +destination texture. + +Mark ClipRectangle as nodiscard to prevent future issues. + +Bug: chromium:1199402 +Change-Id: I260e82d0917b8aa7e7887f2c9f7ed4b1a03ba785 +Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2836786 +Reviewed-by: Jamie Madill +Commit-Queue: Geoff Lang +(cherry picked from commit b574643ef28c92fcea5122dd7a72acb42a514eed) +Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2846982 +Reviewed-by: Geoff Lang + +diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h +index b92e5b439f0678e76404c292d9008099378129be..2ef2aa19dd50a6efac4ac2d4bd0f81fc7ea96d69 100644 +--- a/src/libANGLE/angletypes.h ++++ b/src/libANGLE/angletypes.h +@@ -74,7 +74,7 @@ struct Rectangle + bool operator==(const Rectangle &a, const Rectangle &b); + bool operator!=(const Rectangle &a, const Rectangle &b); + +-bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); ++ANGLE_NO_DISCARD bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); + + struct Offset + { +diff --git a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +index 55f8f8f4d38f30990d7061de6ebaa0595f0447da..6d9365af8db5fa9835127650162d5aeb6ce46b77 100644 +--- a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp ++++ b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +@@ -141,7 +141,10 @@ void StretchedBlitNearest(const gl::Box &sourceArea, + uint8_t *destData) + { + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); +- gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea); ++ if (!gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea)) ++ { ++ return; ++ } + + // Determine if entire rows can be copied at once instead of each individual pixel. There + // must be no out of bounds lookups, whole rows copies, and no scale. +diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp +index 833d4fe9bb1b430c3180f2d663eed1a6fb24e84c..bb56048779bd2dfe5d7d19304686b0ef3585c02e 100644 +--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp ++++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp +@@ -1117,7 +1117,10 @@ angle::Result FramebufferGL::clipSrcRegion(const gl::Context *context, + // If pixels lying outside the read framebuffer, adjust src region + // and dst region to appropriate in-bounds regions respectively. + gl::Rectangle realSourceRegion; +- ClipRectangle(bounds.sourceRegion, bounds.sourceBounds, &realSourceRegion); ++ if (!ClipRectangle(bounds.sourceRegion, bounds.sourceBounds, &realSourceRegion)) ++ { ++ return angle::Result::Stop; ++ } + GLuint xOffset = realSourceRegion.x - bounds.sourceRegion.x; + GLuint yOffset = realSourceRegion.y - bounds.sourceRegion.y; + +diff --git a/src/libANGLE/renderer/metal/ContextMtl.mm b/src/libANGLE/renderer/metal/ContextMtl.mm +index 88c4987433e4351540e8c83e5d9128eaab28b318..b069da6e504cb15150b2ae34b519a3fc9e37731f 100644 +--- a/src/libANGLE/renderer/metal/ContextMtl.mm ++++ b/src/libANGLE/renderer/metal/ContextMtl.mm +@@ -1362,7 +1362,10 @@ bool NeedToInvertDepthRange(float near, float far) + + // Clip the render area to the viewport. + gl::Rectangle viewportClippedRenderArea; +- gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea); ++ if (!gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea)) ++ { ++ viewportClippedRenderArea = gl::Rectangle(); ++ } + + gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false); + if (framebufferMtl->flipY()) +diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp +index 8cdf049cd30a15a30dac06b39e24b39add9a2c5a..433a034b82e7f141ba7f867ad7325ce245b936f7 100644 +--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp ++++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp +@@ -2824,8 +2824,11 @@ angle::Result ContextVk::updateScissorImpl(const gl::State &glState, bool should + + // Clip the render area to the viewport. + gl::Rectangle viewportClippedRenderArea; +- gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()), +- &viewportClippedRenderArea); ++ if (!gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()), ++ &viewportClippedRenderArea)) ++ { ++ viewportClippedRenderArea = gl::Rectangle(); ++ } + + gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false); + gl::Rectangle rotatedScissoredArea; +diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp +index dc5a324684e209e6b50f8d67149c48ad845ae58f..6c4258f36ab64c4ce9d634179b38791a00b4f814 100644 +--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp ++++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp +@@ -2360,6 +2360,30 @@ TEST_P(BlitFramebufferTest, BlitFramebufferSizeOverflow2) + EXPECT_GL_ERROR(GL_INVALID_VALUE); + } + ++// Test an edge case in D3D11 stencil blitting on the CPU that does not properly clip the ++// destination regions ++TEST_P(BlitFramebufferTest, BlitFramebufferStencilClipNoIntersection) ++{ ++ GLFramebuffer framebuffers[2]; ++ glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[0]); ++ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[1]); ++ ++ GLRenderbuffer renderbuffers[2]; ++ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]); ++ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4); ++ glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, ++ renderbuffers[0]); ++ ++ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]); ++ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 4, 4); ++ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, ++ renderbuffers[1]); ++ ++ glBlitFramebuffer(0, 0, 4, 4, 1 << 24, 1 << 24, 1 << 25, 1 << 25, GL_STENCIL_BUFFER_BIT, ++ GL_NEAREST); ++ EXPECT_GL_NO_ERROR(); ++} ++ + // Use this to select which configurations (e.g. which renderer, which GLES major version) these + // tests should be run against. + ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest, diff --git a/patches/config.json b/patches/config.json index 7bffbe04a5a43..4ff406c7514ad 100644 --- a/patches/config.json +++ b/patches/config.json @@ -23,5 +23,7 @@ "src/electron/patches/pdfium": "src/third_party/pdfium", - "src/electron/patches/webrtc": "src/third_party/webrtc" + "src/electron/patches/webrtc": "src/third_party/webrtc", + + "src/electron/patches/angle": "src/third_party/angle" }