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

Commit 54fa17f6 authored by Chris Craik's avatar Chris Craik
Browse files

Add ListView rendering benchmark

Also fixes a bug in DrawRenderNodeOp recording, which was triggered by
the new test.

Change-Id: I328f2ed908495eb95ca8ce87a365d02650e72cd5
parent 9b9eca5c
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1383,7 +1383,10 @@ class DrawRenderNodeOp : public DrawBoundedOp {
    friend class TestUtils;
public:
    DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
            : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr)
            : DrawBoundedOp(0, 0,
                    renderNode->stagingProperties().getWidth(),
                    renderNode->stagingProperties().getHeight(),
                    nullptr)
            , renderNode(renderNode)
            , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
            , localMatrix(transformFromParent)
+16 −15
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "FrameInfoVisualizer.h"

#include "OpenGLRenderer.h"
#include "utils/Color.h"

#include <cutils/compiler.h>
#include <array>
@@ -27,19 +28,19 @@
#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
#define PROFILE_DRAW_DP_PER_MS 7

namespace android {
namespace uirenderer {

// Must be NUM_ELEMENTS in size
static const SkColor THRESHOLD_COLOR = 0xff5faa4d;
static const SkColor BAR_FAST_ALPHA = 0x8F000000;
static const SkColor BAR_JANKY_ALPHA = 0xDF000000;
static const SkColor THRESHOLD_COLOR = Color::Green_500;
static const SkColor BAR_FAST_MASK = 0x8FFFFFFF;
static const SkColor BAR_JANKY_MASK = 0xDFFFFFFF;

// We could get this from TimeLord and use the actual frame interval, but
// this is good enough
#define FRAME_THRESHOLD 16
#define FRAME_THRESHOLD_NS 16000000

namespace android {
namespace uirenderer {

struct BarSegment {
    FrameInfoIndex start;
    FrameInfoIndex end;
@@ -47,13 +48,13 @@ struct BarSegment {
};

static const std::array<BarSegment,7> Bar {{
    { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, 0x00796B },
    { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, 0x388E3C },
    { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x689F38},
    { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, 0x2196F3},
    { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, 0x4FC3F7},
    { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, 0xF44336},
    { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, 0xFF9800},
    { FrameInfoIndex::IntendedVsync, FrameInfoIndex::HandleInputStart, Color::Teal_700 },
    { FrameInfoIndex::HandleInputStart, FrameInfoIndex::PerformTraversalsStart, Color::Green_700 },
    { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, Color::LightGreen_700 },
    { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, Color::Blue_500 },
    { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, Color::LightBlue_300 },
    { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, Color::Red_500},
    { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, Color::Orange_500},
}};

static int dpToPx(int dp, float density) {
@@ -197,9 +198,9 @@ void FrameInfoVisualizer::drawGraph(OpenGLRenderer* canvas) {
    SkPaint paint;
    for (size_t i = 0; i < Bar.size(); i++) {
        nextBarSegment(Bar[i].start, Bar[i].end);
        paint.setColor(Bar[i].color | BAR_FAST_ALPHA);
        paint.setColor(Bar[i].color & BAR_FAST_MASK);
        canvas->drawRects(mFastRects.get(), mNumFastRects * 4, &paint);
        paint.setColor(Bar[i].color | BAR_JANKY_ALPHA);
        paint.setColor(Bar[i].color & BAR_JANKY_MASK);
        canvas->drawRects(mJankyRects.get(), mNumJankyRects * 4, &paint);
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -435,8 +435,9 @@ void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
            refPaint(paint), refBitmap(*bitmap)));
}
void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
    auto&& stagingProps = renderNode->stagingProperties();
    RenderNodeOp* op = new (alloc()) RenderNodeOp(
            Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
            Rect(stagingProps.getWidth(), stagingProps.getHeight()),
            *(mState.currentSnapshot()->transform),
            mState.getRenderTargetClipBounds(),
            renderNode);
+146 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "TestSceneBase.h"
#include "utils/Color.h"

#include <cstdio>

class ListViewAnimation;

static Benchmark _ListView(BenchmarkInfo{
    "listview",
    "A mock ListView of scrolling content. Doesn't re-bind/re-record views as they are recycled, so"
    "won't upload much content (either glyphs, or bitmaps).",
    simpleCreateScene<ListViewAnimation>
});

class ListViewAnimation : public TestScene {
public:
    int cardHeight;
    int cardSpacing;
    int cardWidth;
    int cardLeft;
    sp<RenderNode> listView;
    std::vector< sp<RenderNode> > cards;
    void createContent(int width, int height, TestCanvas& canvas) override {
        srand(0);
        cardHeight = dp(60);
        cardSpacing = dp(16);
        cardWidth = std::min((height - cardSpacing * 2), (int)dp(300));
        cardLeft = (width - cardWidth) / 2;

        for (int y = 0; y < height + (cardHeight + cardSpacing - 1); y += (cardHeight + cardSpacing)) {
            cards.push_back(createCard(cards.size(), y));
        }
        listView = TestUtils::createNode(0, 0, width, height,
                [this](RenderProperties& props, TestCanvas& canvas) {
            for (size_t ci = 0; ci < cards.size(); ci++) {
                canvas.drawRenderNode(cards[ci].get());
            }
        });

        canvas.drawColor(Color::Grey_500, SkXfermode::kSrcOver_Mode);
        canvas.drawRenderNode(listView.get());
    }

    void doFrame(int frameNr) override {
        int scrollPx = dp(frameNr) * 3;
        int cardIndexOffset = scrollPx / (cardSpacing + cardHeight);
        int pxOffset = -(scrollPx % (cardSpacing + cardHeight));

        TestCanvas canvas(cardWidth, cardHeight);
        for (size_t ci = 0; ci < cards.size(); ci++) {
            // update card position
            auto card = cards[(ci + cardIndexOffset) % cards.size()];
            int top = ((int)ci) * (cardSpacing + cardHeight) + pxOffset;
            card->mutateStagingProperties().setLeftTopRightBottom(
                    cardLeft, top, cardLeft + cardWidth, top + cardHeight);
            card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);

            // draw it to parent DisplayList
            canvas.drawRenderNode(cards[ci].get());
        }
        listView->setStagingDisplayList(canvas.finishRecording());
    }
private:
    SkBitmap createRandomCharIcon() {
        int size = cardHeight - (dp(10) * 2);
        SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
        SkCanvas canvas(bitmap);
        canvas.clear(0);

        SkPaint paint;
        paint.setAntiAlias(true);
        SkColor randomColor = BrightColors[rand() % BrightColorsCount];
        paint.setColor(randomColor);
        canvas.drawCircle(size / 2, size / 2, size / 2, paint);

        bool bgDark = SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor)
                < 128 * 3;
        paint.setColor(bgDark ? Color::White : Color::Grey_700);
        paint.setTextAlign(SkPaint::kCenter_Align);
        paint.setTextSize(size / 2);
        char charToShow = 'A' + (rand() % 26);
        canvas.drawText(&charToShow, 1, size / 2, /*approximate centering*/ size * 0.7, paint);
        return bitmap;
    }

    static SkBitmap createBoxBitmap(bool filled) {
        int size = dp(20);
        int stroke = dp(2);
        SkBitmap bitmap = TestUtils::createSkBitmap(size, size);
        SkCanvas canvas(bitmap);
        canvas.clear(Color::Transparent);

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(filled ? Color::Yellow_500 : Color::Grey_700);
        paint.setStyle(filled ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
        paint.setStrokeWidth(stroke);
        canvas.drawRect(SkRect::MakeLTRB(stroke, stroke, size - stroke, size - stroke), paint);
        return bitmap;
    }

    sp<RenderNode> createCard(int cardId, int top) {
        return TestUtils::createNode(cardLeft, top, cardLeft + cardWidth, top + cardHeight,
                [this, cardId](RenderProperties& props, TestCanvas& canvas) {
            static SkBitmap filledBox = createBoxBitmap(true);
            static SkBitmap strokedBox = createBoxBitmap(false);

            props.mutableOutline().setRoundRect(0, 0, cardWidth, cardHeight, dp(6), 1);
            props.mutableOutline().setShouldClip(true);
            canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);

            SkPaint textPaint;
            textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
            textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
            textPaint.setTextSize(dp(20));
            textPaint.setAntiAlias(true);
            char buf[256];
            snprintf(buf, sizeof(buf), "This card is #%d", cardId);
            TestUtils::drawTextToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
            textPaint.setTextSize(dp(15));
            TestUtils::drawTextToCanvas(&canvas, "This is some more text on the card", textPaint,
                    cardHeight, dp(45));

            canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);

            const SkBitmap& boxBitmap = rand() % 2 ? filledBox : strokedBox;
            canvas.drawBitmap(boxBitmap, cardWidth - dp(10) - boxBitmap.width(), dp(10), nullptr);
        });
    }
};
+8 −7
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#include "TestSceneBase.h"
#include "utils/Color.h"

class RecentsAnimation;

@@ -29,16 +30,16 @@ class RecentsAnimation : public TestScene {
public:
    void createContent(int width, int height, TestCanvas& renderer) override {
        static SkColor COLORS[] = {
                0xFFF44336,
                0xFF9C27B0,
                0xFF2196F3,
                0xFF4CAF50,
                Color::Red_500,
                Color::Purple_500,
                Color::Blue_500,
                Color::Green_500,
        };

        thumbnailSize = std::min(std::min(width, height) / 2, 720);
        int cardsize = std::min(width, height) - dp(64);

        renderer.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
        renderer.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
        renderer.insertReorderBarrier(true);

        int x = dp(32);
@@ -63,7 +64,7 @@ public:
            mCards[ci]->setPropertyFieldsDirty(RenderNode::Y);
        }
        mThumbnail.eraseColor(TestUtils::interpolateColor(
                curFrame / 150.0f, 0xFF4CAF50, 0xFFFF5722));
                curFrame / 150.0f, Color::Green_500, Color::DeepOrange_500));
    }

private:
@@ -75,7 +76,7 @@ private:
            props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
            props.mutableOutline().setShouldClip(true);

            canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
            canvas.drawColor(Color::Grey_200, SkXfermode::kSrcOver_Mode);
            canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(),
                    0, 0, width, height, nullptr);
        });
Loading