Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddf2215d authored by Chris Craik's avatar Chris Craik
Browse files

Add partial damage support to new draw path

Change-Id: I612578fd181240de71297c9a28bc9a8f350764a7
parent 80435a7f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -212,10 +212,11 @@ OpReorderer::OpReorderer()
        : mCanvasState(sNullClient) {
}

void OpReorderer::defer(int viewportWidth, int viewportHeight,
void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeight,
        const std::vector< sp<RenderNode> >& nodes) {
    mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
            0, 0, viewportWidth, viewportHeight, Vector3());
            clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
            Vector3());
    for (const sp<RenderNode>& node : nodes) {
        if (node->nothingToDraw()) continue;

@@ -325,7 +326,7 @@ void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) {
// if no target, merging ops still interate to find similar batch to insert after
void OpReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds,
        BatchBase** targetBatch, size_t* insertBatchIndex) const {
    for (size_t i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
    for (int i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
        BatchBase* overBatch = mBatches[i];

        if (overBatch == *targetBatch) break;
+5 −2
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <vector>
#include <unordered_map>

struct SkRect;

namespace android {
namespace uirenderer {

@@ -57,7 +59,8 @@ public:
    OpReorderer();

    // TODO: not final, just presented this way for simplicity. Layers too?
    void defer(int viewportWidth, int viewportHeight, const std::vector< sp<RenderNode> >& nodes);
    void defer(const SkRect& clip, int viewportWidth, int viewportHeight,
            const std::vector< sp<RenderNode> >& nodes);

    void defer(int viewportWidth, int viewportHeight,
            const std::vector<DisplayListData::Chunk>& chunks, const std::vector<RecordedOp*>& ops);
@@ -133,7 +136,7 @@ private:
    // contains ResolvedOps and Batches
    LinearAllocator mAllocator;

    size_t mEarliestBatchIndex = 0;
    int mEarliestBatchIndex = 0;
};

}; // namespace uirenderer
+16 −14
Original line number Diff line number Diff line
@@ -266,11 +266,11 @@ void CanvasContext::draw() {

    Frame frame = mEglManager.beginFrame(mEglSurface);

#if !HWUI_NEW_OPS
    if (frame.width() != mCanvas->getViewportWidth()
            || frame.height() != mCanvas->getViewportHeight()) {
    if (frame.width() != lastFrameWidth || frame.height() != lastFrameHeight) {
        // can't rely on prior content of window if viewport size changes
        dirty.setEmpty();
        lastFrameWidth = frame.width();
        lastFrameHeight = frame.height();
    } else if (mHaveNewSurface || frame.bufferAge() == 0) {
        // New surface needs a full draw
        dirty.setEmpty();
@@ -316,6 +316,18 @@ void CanvasContext::draw() {
    mDamageHistory.next() = screenDirty;

    mEglManager.damageFrame(frame, dirty);

#if HWUI_NEW_OPS
    OpReorderer reorderer;
    reorderer.defer(dirty, frame.width(), frame.height(), mRenderNodes);
    BakedOpRenderer::Info info(Caches::getInstance(), mRenderThread.renderState(),
            frame.width(), frame.height(), mOpaque);
    // TODO: profiler().draw(mCanvas);
    reorderer.replayBakedOps<BakedOpRenderer>(&info);

    bool drew = info.didDraw;

#else
    mCanvas->prepareDirty(frame.width(), frame.height(),
            dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);

@@ -426,20 +438,10 @@ void CanvasContext::draw() {
    profiler().draw(mCanvas);

    bool drew = mCanvas->finish();

#endif
    // Even if we decided to cancel the frame, from the perspective of jank
    // metrics the frame was swapped at this point
    mCurrentFrameInfo->markSwapBuffers();
#else
    OpReorderer reorderer;
    reorderer.defer(frame.width(), frame.height(), mRenderNodes);
    BakedOpRenderer::Info info(Caches::getInstance(), mRenderThread.renderState(),
            frame.width(), frame.height(), mOpaque);
    reorderer.replayBakedOps<BakedOpRenderer>(&info);

    bool drew = info.didDraw;
    SkRect screenDirty = SkRect::MakeWH(frame.width(), frame.height());
#endif

    if (drew) {
        if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) {
+3 −0
Original line number Diff line number Diff line
@@ -141,6 +141,9 @@ private:

    void freePrefetechedLayers();

    int lastFrameWidth = 0;
    int lastFrameHeight = 0;

    RenderThread& mRenderThread;
    EglManager& mEglManager;
    sp<ANativeWindow> mNativeWindow;
+42 −14
Original line number Diff line number Diff line
@@ -50,9 +50,7 @@ public:
};
TEST(OpReorderer, simple) {
    auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
        SkBitmap bitmap;
        bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));

        SkBitmap bitmap = TestUtils::createSkBitmap(25, 25);
        canvas.drawRect(0, 0, 100, 200, SkPaint());
        canvas.drawBitmap(bitmap, 10, 10, nullptr);
    });
@@ -81,8 +79,7 @@ public:
};
TEST(OpReorderer, simpleBatching) {
    auto dld = TestUtils::createDLD<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
        SkBitmap bitmap;
        bitmap.setInfo(SkImageInfo::MakeUnknown(10, 10));
        SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);

        // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
        // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
@@ -151,11 +148,42 @@ TEST(OpReorderer, renderNode) {
    nodes.push_back(parent.get());

    OpReorderer reorderer;
    reorderer.defer(200, 200, nodes);
    reorderer.defer(SkRect::MakeWH(200, 200), 200, 200, nodes);

    Info info;
    reorderer.replayBakedOps<RenderNodeReceiver>(&info);
}

class ClippedReceiver {
public:
    static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
        EXPECT_EQ(0, info->index++);
        EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds);
        EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect);
        EXPECT_TRUE(state.computedState.transform.isIdentity());
    }
    UNSUPPORTED_OP(Info, RectOp)
    UNSUPPORTED_OP(Info, RenderNodeOp)
    UNSUPPORTED_OP(Info, SimpleRectsOp)
    static void startFrame(Info& info) {}
    static void endFrame(Info& info) {}
};
TEST(OpReorderer, clipped) {
    sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RecordingCanvas& canvas) {
        SkBitmap bitmap = TestUtils::createSkBitmap(200, 200);
        canvas.drawBitmap(bitmap, 0, 0, nullptr);
    });
    TestUtils::syncNodePropertiesAndDisplayList(node);
    std::vector< sp<RenderNode> > nodes;
    nodes.push_back(node.get());

    OpReorderer reorderer;
    reorderer.defer(SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
            200, 200, nodes);

    Info info;
    reorderer.replayBakedOps<ClippedReceiver>(&info);
}

}
}
Loading