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

Commit 2eb4ca61 authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Add partial damage support to new draw path"

parents 5dd239a1 ddf2215d
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