Merge changes I9a231625,Idaf3a905 into sc-dev
* changes: Avoid creating a layer for linear stretch Add a stretchy benchmark
This commit is contained in:
committed by
Android (Google) Code Review
commit
46614cfa99
@@ -553,7 +553,7 @@ public:
|
|||||||
bool promotedToLayer() const {
|
bool promotedToLayer() const {
|
||||||
return mLayerProperties.mType == LayerType::None && fitsOnLayer() &&
|
return mLayerProperties.mType == LayerType::None && fitsOnLayer() &&
|
||||||
(mComputedFields.mNeedLayerForFunctors || mLayerProperties.mImageFilter != nullptr ||
|
(mComputedFields.mNeedLayerForFunctors || mLayerProperties.mImageFilter != nullptr ||
|
||||||
!mLayerProperties.getStretchEffect().isEmpty() ||
|
mLayerProperties.getStretchEffect().requiresLayer() ||
|
||||||
(!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 &&
|
(!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 &&
|
||||||
mPrimitiveFields.mHasOverlappingRendering));
|
mPrimitiveFields.mHasOverlappingRendering));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Properties.h"
|
||||||
#include "utils/MathUtils.h"
|
#include "utils/MathUtils.h"
|
||||||
|
|
||||||
#include <SkImage.h>
|
#include <SkImage.h>
|
||||||
@@ -108,6 +109,11 @@ public:
|
|||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool requiresLayer() const {
|
||||||
|
return !(isEmpty() ||
|
||||||
|
Properties::stretchEffectBehavior == StretchEffectBehavior::LinearScale);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static sk_sp<SkRuntimeEffect> getStretchEffect();
|
static sk_sp<SkRuntimeEffect> getStretchEffect();
|
||||||
mutable SkVector mStretchDirection{0, 0};
|
mutable SkVector mStretchDirection{0, 0};
|
||||||
|
|||||||
@@ -171,16 +171,11 @@ void RenderNodeDrawable::forceDraw(SkCanvas* canvas) const {
|
|||||||
displayList->mProjectedOutline = nullptr;
|
displayList->mProjectedOutline = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stretchNeedsLayer(const LayerProperties& properties) {
|
|
||||||
return Properties::stretchEffectBehavior != StretchEffectBehavior::LinearScale &&
|
|
||||||
!properties.getStretchEffect().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool layerNeedsPaint(const sk_sp<SkImage>& snapshotImage, const LayerProperties& properties,
|
static bool layerNeedsPaint(const sk_sp<SkImage>& snapshotImage, const LayerProperties& properties,
|
||||||
float alphaMultiplier, SkPaint* paint) {
|
float alphaMultiplier, SkPaint* paint) {
|
||||||
if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
|
if (alphaMultiplier < 1.0f || properties.alpha() < 255 ||
|
||||||
properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr ||
|
properties.xferMode() != SkBlendMode::kSrcOver || properties.getColorFilter() != nullptr ||
|
||||||
properties.getImageFilter() != nullptr || stretchNeedsLayer(properties)) {
|
properties.getImageFilter() != nullptr || properties.getStretchEffect().requiresLayer()) {
|
||||||
paint->setAlpha(properties.alpha() * alphaMultiplier);
|
paint->setAlpha(properties.alpha() * alphaMultiplier);
|
||||||
paint->setBlendMode(properties.xferMode());
|
paint->setBlendMode(properties.xferMode());
|
||||||
paint->setColorFilter(sk_ref_sp(properties.getColorFilter()));
|
paint->setColorFilter(sk_ref_sp(properties.getColorFilter()));
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ namespace test {
|
|||||||
class TestScene {
|
class TestScene {
|
||||||
public:
|
public:
|
||||||
struct Options {
|
struct Options {
|
||||||
int count = 0;
|
int frameCount = 150;
|
||||||
|
int repeatCount = 1;
|
||||||
int reportFrametimeWeight = 0;
|
int reportFrametimeWeight = 0;
|
||||||
bool renderOffscreen = true;
|
bool renderOffscreen = true;
|
||||||
};
|
};
|
||||||
|
|||||||
200
libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
Normal file
200
libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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 <SkFont.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include "TestSceneBase.h"
|
||||||
|
#include "hwui/Paint.h"
|
||||||
|
#include "tests/common/TestUtils.h"
|
||||||
|
|
||||||
|
class StretchyListViewAnimation;
|
||||||
|
class StretchyListViewHolePunch;
|
||||||
|
class StretchyLinearListView;
|
||||||
|
class StretchyLinearListViewHolePunch;
|
||||||
|
|
||||||
|
static TestScene::Registrar _StretchyListViewAnimation(TestScene::Info{
|
||||||
|
"stretchylistview",
|
||||||
|
"A mock ListView of scrolling content that's stretching. Doesn't re-bind/re-record views "
|
||||||
|
"as they are recycled, so won't upload much content (either glyphs, or bitmaps).",
|
||||||
|
TestScene::simpleCreateScene<StretchyListViewAnimation>});
|
||||||
|
|
||||||
|
static TestScene::Registrar _StretchyListViewHolePunch(TestScene::Info{
|
||||||
|
"stretchylistview_holepunch",
|
||||||
|
"A mock ListView of scrolling content that's stretching. Includes a hole punch",
|
||||||
|
TestScene::simpleCreateScene<StretchyListViewHolePunch>});
|
||||||
|
|
||||||
|
static TestScene::Registrar _StretchyLinearListView(TestScene::Info{
|
||||||
|
"stretchylistview_linear",
|
||||||
|
"A mock ListView of scrolling content that's stretching using a linear stretch effect.",
|
||||||
|
TestScene::simpleCreateScene<StretchyLinearListView>});
|
||||||
|
|
||||||
|
static TestScene::Registrar _StretchyLinearListViewHolePunch(TestScene::Info{
|
||||||
|
"stretchylistview_linear_holepunch",
|
||||||
|
"A mock ListView of scrolling content that's stretching using a linear stretch effect. "
|
||||||
|
"Includes a hole punch",
|
||||||
|
TestScene::simpleCreateScene<StretchyLinearListViewHolePunch>});
|
||||||
|
|
||||||
|
class StretchyListViewAnimation : public TestScene {
|
||||||
|
protected:
|
||||||
|
virtual StretchEffectBehavior stretchBehavior() { return StretchEffectBehavior::Shader; }
|
||||||
|
virtual bool haveHolePunch() { return false; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mItemHeight;
|
||||||
|
int mItemSpacing;
|
||||||
|
int mItemWidth;
|
||||||
|
int mItemLeft;
|
||||||
|
sp<RenderNode> mListView;
|
||||||
|
std::vector<sp<RenderNode> > mListItems;
|
||||||
|
|
||||||
|
sk_sp<Bitmap> createRandomCharIcon(int cardHeight) {
|
||||||
|
SkBitmap skBitmap;
|
||||||
|
int size = cardHeight - (dp(10) * 2);
|
||||||
|
sk_sp<Bitmap> bitmap(TestUtils::createBitmap(size, size, &skBitmap));
|
||||||
|
SkCanvas canvas(skBitmap);
|
||||||
|
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);
|
||||||
|
|
||||||
|
SkFont font;
|
||||||
|
font.setSize(size / 2);
|
||||||
|
char charToShow = 'A' + (rand() % 26);
|
||||||
|
const SkPoint pos = {SkIntToScalar(size / 2),
|
||||||
|
/*approximate centering*/ SkFloatToScalar(size * 0.7f)};
|
||||||
|
canvas.drawSimpleText(&charToShow, 1, SkTextEncoding::kUTF8, pos.fX, pos.fY, font, paint);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sk_sp<Bitmap> createBoxBitmap(bool filled) {
|
||||||
|
int size = dp(20);
|
||||||
|
int stroke = dp(2);
|
||||||
|
SkBitmap skBitmap;
|
||||||
|
auto bitmap = TestUtils::createBitmap(size, size, &skBitmap);
|
||||||
|
SkCanvas canvas(skBitmap);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createListItem(RenderProperties& props, Canvas& canvas, int cardId, int itemWidth,
|
||||||
|
int itemHeight) {
|
||||||
|
static sk_sp<Bitmap> filledBox(createBoxBitmap(true));
|
||||||
|
static sk_sp<Bitmap> strokedBox(createBoxBitmap(false));
|
||||||
|
const bool addHolePunch = cardId == 2 && haveHolePunch();
|
||||||
|
// TODO: switch to using round rect clipping, once merging correctly handles that
|
||||||
|
Paint roundRectPaint;
|
||||||
|
roundRectPaint.setAntiAlias(true);
|
||||||
|
roundRectPaint.setColor(Color::White);
|
||||||
|
if (addHolePunch) {
|
||||||
|
// Punch a hole but then cover it up, we don't want to actually see it
|
||||||
|
canvas.punchHole(SkRRect::MakeRect(SkRect::MakeWH(itemWidth, itemHeight)));
|
||||||
|
}
|
||||||
|
canvas.drawRoundRect(0, 0, itemWidth, itemHeight, dp(6), dp(6), roundRectPaint);
|
||||||
|
|
||||||
|
Paint textPaint;
|
||||||
|
textPaint.setColor(rand() % 2 ? Color::Black : Color::Grey_500);
|
||||||
|
textPaint.getSkFont().setSize(dp(20));
|
||||||
|
textPaint.setAntiAlias(true);
|
||||||
|
char buf[256];
|
||||||
|
snprintf(buf, sizeof(buf), "This card is #%d", cardId);
|
||||||
|
TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, itemHeight, dp(25));
|
||||||
|
textPaint.getSkFont().setSize(dp(15));
|
||||||
|
if (addHolePunch) {
|
||||||
|
TestUtils::drawUtf8ToCanvas(&canvas, "I have a hole punch", textPaint, itemHeight,
|
||||||
|
dp(45));
|
||||||
|
} else {
|
||||||
|
TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
|
||||||
|
itemHeight, dp(45));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto randomIcon = createRandomCharIcon(itemHeight);
|
||||||
|
canvas.drawBitmap(*randomIcon, dp(10), dp(10), nullptr);
|
||||||
|
|
||||||
|
auto box = rand() % 2 ? filledBox : strokedBox;
|
||||||
|
canvas.drawBitmap(*box, itemWidth - dp(10) - box->width(), dp(10), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createContent(int width, int height, Canvas& canvas) override {
|
||||||
|
srand(0);
|
||||||
|
mItemHeight = dp(60);
|
||||||
|
mItemSpacing = dp(16);
|
||||||
|
mItemWidth = std::min((height - mItemSpacing * 2), (int)dp(300));
|
||||||
|
mItemLeft = (width - mItemWidth) / 2;
|
||||||
|
int heightWithSpacing = mItemHeight + mItemSpacing;
|
||||||
|
for (int y = 0; y < height + (heightWithSpacing - 1); y += heightWithSpacing) {
|
||||||
|
int id = mListItems.size();
|
||||||
|
auto node = TestUtils::createNode(mItemLeft, y, mItemLeft + mItemWidth, y + mItemHeight,
|
||||||
|
[this, id](RenderProperties& props, Canvas& canvas) {
|
||||||
|
createListItem(props, canvas, id, mItemWidth,
|
||||||
|
mItemHeight);
|
||||||
|
});
|
||||||
|
mListItems.push_back(node);
|
||||||
|
}
|
||||||
|
mListView = TestUtils::createNode(0, 0, width, height,
|
||||||
|
[this](RenderProperties& props, Canvas& canvas) {
|
||||||
|
for (size_t ci = 0; ci < mListItems.size(); ci++) {
|
||||||
|
canvas.drawRenderNode(mListItems[ci].get());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.drawColor(Color::Grey_500, SkBlendMode::kSrcOver);
|
||||||
|
canvas.drawRenderNode(mListView.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void doFrame(int frameNr) override {
|
||||||
|
if (frameNr == 0) {
|
||||||
|
Properties::stretchEffectBehavior = stretchBehavior();
|
||||||
|
}
|
||||||
|
auto& props = mListView->mutateStagingProperties();
|
||||||
|
auto& stretch = props.mutateLayerProperties().mutableStretchEffect();
|
||||||
|
stretch.setEmpty();
|
||||||
|
frameNr = frameNr % 150;
|
||||||
|
// Animate from 0f to .1f
|
||||||
|
const float sY = (frameNr > 75 ? 150 - frameNr : frameNr) / 1500.f;
|
||||||
|
stretch.mergeWith({{.fX = 0, .fY = sY},
|
||||||
|
static_cast<float>(props.getWidth()),
|
||||||
|
static_cast<float>(props.getHeight())});
|
||||||
|
mListView->setPropertyFieldsDirty(RenderNode::GENERIC);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class StretchyListViewHolePunch : public StretchyListViewAnimation {
|
||||||
|
bool haveHolePunch() override { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class StretchyLinearListView : public StretchyListViewAnimation {
|
||||||
|
StretchEffectBehavior stretchBehavior() override { return StretchEffectBehavior::LinearScale; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class StretchyLinearListViewHolePunch : public StretchyListViewAnimation {
|
||||||
|
StretchEffectBehavior stretchBehavior() override { return StretchEffectBehavior::LinearScale; }
|
||||||
|
bool haveHolePunch() override { return true; }
|
||||||
|
};
|
||||||
@@ -62,53 +62,23 @@ private:
|
|||||||
T mAverage;
|
T mAverage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using BenchmarkResults = std::vector<benchmark::BenchmarkReporter::Run>;
|
||||||
|
|
||||||
void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts,
|
void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options& opts,
|
||||||
benchmark::BenchmarkReporter* reporter, RenderProxy* proxy,
|
double durationInS, int repetationIndex, BenchmarkResults* reports) {
|
||||||
double durationInS) {
|
benchmark::BenchmarkReporter::Run report;
|
||||||
using namespace benchmark;
|
report.repetitions = opts.repeatCount;
|
||||||
|
report.repetition_index = repetationIndex;
|
||||||
struct ReportInfo {
|
|
||||||
int percentile;
|
|
||||||
const char* suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::array<ReportInfo, 4> REPORTS = {
|
|
||||||
ReportInfo{50, "_50th"}, ReportInfo{90, "_90th"}, ReportInfo{95, "_95th"},
|
|
||||||
ReportInfo{99, "_99th"},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Although a vector is used, it must stay with only a single element
|
|
||||||
// otherwise the BenchmarkReporter will automatically compute
|
|
||||||
// mean and stddev which doesn't make sense for our usage
|
|
||||||
std::vector<BenchmarkReporter::Run> reports;
|
|
||||||
BenchmarkReporter::Run report;
|
|
||||||
report.run_name.function_name = info.name;
|
report.run_name.function_name = info.name;
|
||||||
report.iterations = static_cast<int64_t>(opts.count);
|
report.iterations = static_cast<int64_t>(opts.frameCount);
|
||||||
report.real_accumulated_time = durationInS;
|
report.real_accumulated_time = durationInS;
|
||||||
report.cpu_accumulated_time = durationInS;
|
report.cpu_accumulated_time = durationInS;
|
||||||
report.counters["items_per_second"] = opts.count / durationInS;
|
report.counters["items_per_second"] = opts.frameCount / durationInS;
|
||||||
reports.push_back(report);
|
reports->push_back(report);
|
||||||
reporter->ReportRuns(reports);
|
|
||||||
|
|
||||||
// Pretend the percentiles are single-iteration runs of the test
|
|
||||||
// If rendering offscreen skip this as it's fps that's more interesting
|
|
||||||
// in that test case than percentiles.
|
|
||||||
if (!opts.renderOffscreen) {
|
|
||||||
for (auto& ri : REPORTS) {
|
|
||||||
reports[0].run_name.function_name = info.name;
|
|
||||||
reports[0].run_name.function_name += ri.suffix;
|
|
||||||
durationInS = proxy->frameTimePercentile(ri.percentile) / 1000.0;
|
|
||||||
reports[0].real_accumulated_time = durationInS;
|
|
||||||
reports[0].cpu_accumulated_time = durationInS;
|
|
||||||
reports[0].iterations = 1;
|
|
||||||
reports[0].counters["items_per_second"] = 0;
|
|
||||||
reporter->ReportRuns(reports);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const TestScene::Info& info, const TestScene::Options& opts,
|
static void doRun(const TestScene::Info& info, const TestScene::Options& opts, int repetitionIndex,
|
||||||
benchmark::BenchmarkReporter* reporter) {
|
BenchmarkResults* reports) {
|
||||||
Properties::forceDrawFrame = true;
|
Properties::forceDrawFrame = true;
|
||||||
TestContext testContext;
|
TestContext testContext;
|
||||||
testContext.setRenderOffscreen(opts.renderOffscreen);
|
testContext.setRenderOffscreen(opts.renderOffscreen);
|
||||||
@@ -158,7 +128,7 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
|
|||||||
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
|
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
|
||||||
|
|
||||||
nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
|
nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
for (int i = 0; i < opts.count; i++) {
|
for (int i = 0; i < opts.frameCount; i++) {
|
||||||
testContext.waitForVsync();
|
testContext.waitForVsync();
|
||||||
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
|
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
{
|
{
|
||||||
@@ -182,9 +152,24 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
|
|||||||
proxy->fence();
|
proxy->fence();
|
||||||
nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
|
nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
|
||||||
if (reporter) {
|
if (reports) {
|
||||||
outputBenchmarkReport(info, opts, reporter, proxy.get(), (end - start) / (double)s2ns(1));
|
outputBenchmarkReport(info, opts, (end - start) / (double)s2ns(1), repetitionIndex,
|
||||||
|
reports);
|
||||||
} else {
|
} else {
|
||||||
proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
|
proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void run(const TestScene::Info& info, const TestScene::Options& opts,
|
||||||
|
benchmark::BenchmarkReporter* reporter) {
|
||||||
|
BenchmarkResults results;
|
||||||
|
for (int i = 0; i < opts.repeatCount; i++) {
|
||||||
|
doRun(info, opts, i, reporter ? &results : nullptr);
|
||||||
|
}
|
||||||
|
if (reporter) {
|
||||||
|
reporter->ReportRuns(results);
|
||||||
|
if (results.size() > 1) {
|
||||||
|
// TODO: Report summary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ using namespace android;
|
|||||||
using namespace android::uirenderer;
|
using namespace android::uirenderer;
|
||||||
using namespace android::uirenderer::test;
|
using namespace android::uirenderer::test;
|
||||||
|
|
||||||
static int gRepeatCount = 1;
|
|
||||||
static std::vector<TestScene::Info> gRunTests;
|
static std::vector<TestScene::Info> gRunTests;
|
||||||
static TestScene::Options gOpts;
|
static TestScene::Options gOpts;
|
||||||
|
static bool gRunLeakCheck = true;
|
||||||
std::unique_ptr<benchmark::BenchmarkReporter> gBenchmarkReporter;
|
std::unique_ptr<benchmark::BenchmarkReporter> gBenchmarkReporter;
|
||||||
|
|
||||||
void run(const TestScene::Info& info, const TestScene::Options& opts,
|
void run(const TestScene::Info& info, const TestScene::Options& opts,
|
||||||
@@ -69,6 +69,7 @@ OPTIONS:
|
|||||||
are offscreen rendered
|
are offscreen rendered
|
||||||
--benchmark_format Set output format. Possible values are tabular, json, csv
|
--benchmark_format Set output format. Possible values are tabular, json, csv
|
||||||
--renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk
|
--renderer=TYPE Sets the render pipeline to use. May be skiagl or skiavk
|
||||||
|
--skip-leak-check Skips the memory leak check
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +171,7 @@ enum {
|
|||||||
Onscreen,
|
Onscreen,
|
||||||
Offscreen,
|
Offscreen,
|
||||||
Renderer,
|
Renderer,
|
||||||
|
SkipLeakCheck,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +187,7 @@ static const struct option LONG_OPTIONS[] = {
|
|||||||
{"onscreen", no_argument, nullptr, LongOpts::Onscreen},
|
{"onscreen", no_argument, nullptr, LongOpts::Onscreen},
|
||||||
{"offscreen", no_argument, nullptr, LongOpts::Offscreen},
|
{"offscreen", no_argument, nullptr, LongOpts::Offscreen},
|
||||||
{"renderer", required_argument, nullptr, LongOpts::Renderer},
|
{"renderer", required_argument, nullptr, LongOpts::Renderer},
|
||||||
|
{"skip-leak-check", no_argument, nullptr, LongOpts::SkipLeakCheck},
|
||||||
{0, 0, 0, 0}};
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
static const char* SHORT_OPTIONS = "c:r:h";
|
static const char* SHORT_OPTIONS = "c:r:h";
|
||||||
@@ -214,20 +217,20 @@ void parseOptions(int argc, char* argv[]) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
gOpts.count = atoi(optarg);
|
gOpts.frameCount = atoi(optarg);
|
||||||
if (!gOpts.count) {
|
if (!gOpts.frameCount) {
|
||||||
fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
|
fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
gRepeatCount = atoi(optarg);
|
gOpts.repeatCount = atoi(optarg);
|
||||||
if (!gRepeatCount) {
|
if (!gOpts.repeatCount) {
|
||||||
fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
|
fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
|
||||||
error = true;
|
error = true;
|
||||||
} else {
|
} else {
|
||||||
gRepeatCount = (gRepeatCount > 0 ? gRepeatCount : INT_MAX);
|
gOpts.repeatCount = (gOpts.repeatCount > 0 ? gOpts.repeatCount : INT_MAX);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -283,6 +286,10 @@ void parseOptions(int argc, char* argv[]) {
|
|||||||
gOpts.renderOffscreen = true;
|
gOpts.renderOffscreen = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LongOpts::SkipLeakCheck:
|
||||||
|
gRunLeakCheck = false;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
printHelp();
|
printHelp();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@@ -322,9 +329,6 @@ void parseOptions(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// set defaults
|
|
||||||
gOpts.count = 150;
|
|
||||||
|
|
||||||
Typeface::setRobotoTypefaceForTest();
|
Typeface::setRobotoTypefaceForTest();
|
||||||
|
|
||||||
parseOptions(argc, argv);
|
parseOptions(argc, argv);
|
||||||
@@ -345,10 +349,8 @@ int main(int argc, char* argv[]) {
|
|||||||
gBenchmarkReporter->ReportContext(context);
|
gBenchmarkReporter->ReportContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < gRepeatCount; i++) {
|
for (auto&& test : gRunTests) {
|
||||||
for (auto&& test : gRunTests) {
|
run(test, gOpts, gBenchmarkReporter.get());
|
||||||
run(test, gOpts, gBenchmarkReporter.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gBenchmarkReporter) {
|
if (gBenchmarkReporter) {
|
||||||
@@ -358,6 +360,8 @@ int main(int argc, char* argv[]) {
|
|||||||
renderthread::RenderProxy::trimMemory(100);
|
renderthread::RenderProxy::trimMemory(100);
|
||||||
HardwareBitmapUploader::terminate();
|
HardwareBitmapUploader::terminate();
|
||||||
|
|
||||||
LeakChecker::checkForLeaks();
|
if (gRunLeakCheck) {
|
||||||
|
LeakChecker::checkForLeaks();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user