diff options
author | 2016-02-03 19:45:06 -0800 | |
---|---|---|
committer | 2016-02-03 20:09:00 -0800 | |
commit | 7fc1b0349bc2ac8c880120dc5611f703faa7f06f (patch) | |
tree | 6eb28dc729ca8fcecc3be81bffb27828e32052e9 | |
parent | d38308e4d0599836f9c5446ba9d6edbc0713c428 (diff) |
Fix ripple clipping + quick rejection
bug:26524690
Don't intersect the first clip with the viewport. Instead, the first
clip op should always be a replace op.
Additionally, only quick reject nodes that clip to bounds, since some
nodes (like ripples) draw outside their own bounds.
Change-Id: I96a52029f360328aba19af7349888cc0a026b5b1
-rw-r--r-- | libs/hwui/ClipArea.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/tests/unit/RecordingCanvasTests.cpp | 17 |
3 files changed, 23 insertions, 1 deletions
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp index 160090dcd8cc..9c08b4dd22ae 100644 --- a/libs/hwui/ClipArea.cpp +++ b/libs/hwui/ClipArea.cpp @@ -213,6 +213,7 @@ void ClipArea::setClip(float left, float top, float right, float bottom) { void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op) { + if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; onClipUpdated(); switch (mMode) { case ClipMode::Rectangle: @@ -228,6 +229,7 @@ void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, } void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { + if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; onClipUpdated(); enterRegionMode(); mClipRegion.op(region, op); @@ -236,6 +238,7 @@ void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op) { + if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; onClipUpdated(); SkMatrix skTransform; transform->copyTo(skTransform); diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index a45721249542..1c765f65eb8f 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -208,7 +208,9 @@ void FrameBuilder::deferNodePropsAndOps(RenderNode& node) { mCanvasState.setClippingOutline(mAllocator, &(properties.getOutline())); } - if (!mCanvasState.quickRejectConservative(0, 0, width, height)) { + bool quickRejected = properties.getClipToBounds() + && mCanvasState.quickRejectConservative(0, 0, width, height); + if (!quickRejected) { // not rejected, so defer render as either Layer, or direct (possibly wrapped in saveLayer) if (node.getLayer()) { // HW layer diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp index 01bfc5adbbbd..20d2f1f18c58 100644 --- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp +++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp @@ -455,6 +455,23 @@ TEST(RecordingCanvas, drawRenderNode_projection) { } } +TEST(RecordingCanvas, firstClipWillReplace) { + auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { + canvas.save(SaveFlags::MatrixClip); + // since no explicit clip set on canvas, this should be the one observed on op: + canvas.clipRect(-100, -100, 300, 300, SkRegion::kIntersect_Op); + + SkPaint paint; + paint.setColor(SK_ColorWHITE); + canvas.drawRect(0, 0, 100, 100, paint); + + canvas.restore(); + }); + ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op"; + // first clip must be preserved, even if it extends beyond canvas bounds + EXPECT_CLIP_RECT(Rect(-100, -100, 300, 300), dl->getOps()[0]->localClip); +} + TEST(RecordingCanvas, insertReorderBarrier) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { canvas.drawRect(0, 0, 400, 400, SkPaint()); |