diff options
-rw-r--r-- | libs/hwui/OpReorderer.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/tests/unit/OpReordererTests.cpp | 40 |
2 files changed, 46 insertions, 12 deletions
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp index bdc8f68cf3b8..ad9559ffdf9f 100644 --- a/libs/hwui/OpReorderer.cpp +++ b/libs/hwui/OpReorderer.cpp @@ -91,8 +91,7 @@ public: MergingOpBatch(batchid_t batchId, BakedOpState* op) : BatchBase(batchId, op, true) - , mClipSideFlags(op->computedState.clipSideFlags) - , mClipRect(op->computedState.clipRect) { + , mClipSideFlags(op->computedState.clipSideFlags) { } /* @@ -194,22 +193,17 @@ public: mBounds.unionWith(op->computedState.clippedBounds); mOps.push_back(op); - const int newClipSideFlags = op->computedState.clipSideFlags; - mClipSideFlags |= newClipSideFlags; - - const Rect& opClip = op->computedState.clipRect; - if (newClipSideFlags & OpClipSideFlags::Left) mClipRect.left = opClip.left; - if (newClipSideFlags & OpClipSideFlags::Top) mClipRect.top = opClip.top; - if (newClipSideFlags & OpClipSideFlags::Right) mClipRect.right = opClip.right; - if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom; + // Because a new op must have passed canMergeWith(), we know it's passed the clipping compat + // check, and doesn't extend past a side of the clip that's in use by the merged batch. + // Therefore it's safe to simply always merge flags, and use the bounds as the clip rect. + mClipSideFlags |= op->computedState.clipSideFlags; } int getClipSideFlags() const { return mClipSideFlags; } - const Rect& getClipRect() const { return mClipRect; } + const Rect& getClipRect() const { return mBounds; } private: int mClipSideFlags; - Rect mClipRect; }; OpReorderer::LayerReorderer::LayerReorderer(uint32_t width, uint32_t height, diff --git a/libs/hwui/tests/unit/OpReordererTests.cpp b/libs/hwui/tests/unit/OpReordererTests.cpp index 288f8af50081..b28e4361bc4a 100644 --- a/libs/hwui/tests/unit/OpReordererTests.cpp +++ b/libs/hwui/tests/unit/OpReordererTests.cpp @@ -222,6 +222,46 @@ TEST(OpReorderer, simpleBatching) { << "Expect number of ops = 2 * loop count"; } +TEST(OpReorderer, clippedMerging) { + class ClippedMergingTestRenderer : public TestRendererBase { + public: + void onMergedBitmapOps(const MergedBakedOpList& opList) override { + EXPECT_EQ(0, mIndex); + mIndex += opList.count; + EXPECT_EQ(4u, opList.count); + EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); + EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, + opList.clipSideFlags); + } + }; + auto node = TestUtils::createNode(0, 0, 100, 100, + [](RenderProperties& props, TestCanvas& canvas) { + SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); + + // left side clipped (to inset left half) + canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); + canvas.drawBitmap(bitmap, 0, 40, nullptr); + + // top side clipped (to inset top half) + canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); + canvas.drawBitmap(bitmap, 40, 0, nullptr); + + // right side clipped (to inset right half) + canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); + canvas.drawBitmap(bitmap, 80, 40, nullptr); + + // bottom not clipped, just abutting (inset bottom half) + canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); + canvas.drawBitmap(bitmap, 40, 70, nullptr); + }); + + OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, + createSyncedNodeList(node), sLightCenter); + ClippedMergingTestRenderer renderer; + reorderer.replayBakedOps<TestDispatcher>(renderer); + EXPECT_EQ(4, renderer.getIndex()); +} + TEST(OpReorderer, textMerging) { class TextMergingTestRenderer : public TestRendererBase { public: |