Build hwui test scenes as common test code
And start using them in other non-macrobench tests
Change-Id: If155b531f3c89f97491001c06d1996df527b9f85
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d98497b..0d1ee46 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -90,6 +90,9 @@
protos/hwui.proto
hwui_test_common_src_files := \
+ $(call all-cpp-files-under, tests/common/scenes) \
+ tests/common/TestContext.cpp \
+ tests/common/TestScene.cpp \
tests/common/TestUtils.cpp
hwui_cflags := \
@@ -259,12 +262,9 @@
LOCAL_SRC_FILES += \
$(hwui_test_common_src_files) \
- tests/macrobench/TestContext.cpp \
tests/macrobench/TestSceneRunner.cpp \
tests/macrobench/main.cpp
-LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/common/scenes)
-
include $(BUILD_EXECUTABLE)
# ------------------------
diff --git a/libs/hwui/tests/macrobench/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
similarity index 98%
rename from libs/hwui/tests/macrobench/TestContext.cpp
rename to libs/hwui/tests/common/TestContext.cpp
index ba763a8..146e735 100644
--- a/libs/hwui/tests/macrobench/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "TestContext.h"
+#include "tests/common/TestContext.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/tests/macrobench/TestContext.h b/libs/hwui/tests/common/TestContext.h
similarity index 100%
rename from libs/hwui/tests/macrobench/TestContext.h
rename to libs/hwui/tests/common/TestContext.h
diff --git a/libs/hwui/tests/common/TestScene.cpp b/libs/hwui/tests/common/TestScene.cpp
new file mode 100644
index 0000000..02bcd47
--- /dev/null
+++ b/libs/hwui/tests/common/TestScene.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "tests/common/TestScene.h"
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+// Not a static global because we need to force the map to be constructed
+// before we try to add things to it.
+std::unordered_map<std::string, TestScene::Info>& TestScene::testMap() {
+ static std::unordered_map<std::string, TestScene::Info> testMap;
+ return testMap;
+}
+
+void TestScene::registerScene(const TestScene::Info& info) {
+ testMap()[info.name] = info;
+}
+
+} /* namespace test */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/tests/common/TestScene.h b/libs/hwui/tests/common/TestScene.h
index b5d8954..df8d194 100644
--- a/libs/hwui/tests/common/TestScene.h
+++ b/libs/hwui/tests/common/TestScene.h
@@ -16,6 +16,9 @@
#ifndef TESTS_TESTSCENE_H
#define TESTS_TESTSCENE_H
+#include <string>
+#include <unordered_map>
+
namespace android {
namespace uirenderer {
class RenderNode;
@@ -32,9 +35,40 @@
class TestScene {
public:
+ struct Options {
+ int count = 0;
+ };
+
+ template <class T>
+ static test::TestScene* simpleCreateScene(const TestScene::Options&) {
+ return new T();
+ }
+
+ typedef test::TestScene* (*CreateScene)(const TestScene::Options&);
+
+ struct Info {
+ std::string name;
+ std::string description;
+ CreateScene createScene;
+ };
+
+ class Registrar {
+ public:
+ Registrar(const TestScene::Info& info) {
+ TestScene::registerScene(info);
+ }
+ private:
+ Registrar() = delete;
+ Registrar(const Registrar&) = delete;
+ Registrar& operator=(const Registrar&) = delete;
+ };
+
virtual ~TestScene() {}
virtual void createContent(int width, int height, TestCanvas& renderer) = 0;
virtual void doFrame(int frameNr) = 0;
+
+ static std::unordered_map<std::string, Info>& testMap();
+ static void registerScene(const Info& info);
};
} // namespace test
diff --git a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
index e316eca..c212df4 100644
--- a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
@@ -18,11 +18,11 @@
class HwLayerAnimation;
-static Benchmark _HwLayer(BenchmarkInfo{
+static TestScene::Registrar _HwLayer(TestScene::Info{
"hwlayer",
"A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
"Tests the hardware layer codepath.",
- simpleCreateScene<HwLayerAnimation>
+ TestScene::simpleCreateScene<HwLayerAnimation>
});
class HwLayerAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index 6c64a32..43e247e 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -21,11 +21,11 @@
class ListViewAnimation;
-static Benchmark _ListView(BenchmarkInfo{
+static TestScene::Registrar _ListView(TestScene::Info{
"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>
+ TestScene::simpleCreateScene<ListViewAnimation>
});
class ListViewAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
index 936aba1..082c628 100644
--- a/libs/hwui/tests/common/scenes/OvalAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
@@ -18,10 +18,10 @@
class OvalAnimation;
-static Benchmark _Oval(BenchmarkInfo{
+static TestScene::Registrar _Oval(TestScene::Info{
"oval",
"Draws 1 oval.",
- simpleCreateScene<OvalAnimation>
+ TestScene::simpleCreateScene<OvalAnimation>
});
class OvalAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
index c31ddd1..84265a4 100644
--- a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
@@ -18,12 +18,12 @@
class PartialDamageAnimation;
-static Benchmark _PartialDamage(BenchmarkInfo{
+static TestScene::Registrar _PartialDamage(TestScene::Info{
"partialdamage",
"Tests the partial invalidation path. Draws a grid of rects and animates 1 "
"of them, should be low CPU & GPU load if EGL_EXT_buffer_age or "
"EGL_KHR_partial_update is supported by the device & are enabled in hwui.",
- simpleCreateScene<PartialDamageAnimation>
+ TestScene::simpleCreateScene<PartialDamageAnimation>
});
class PartialDamageAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
index 5d4ef96..6509edd 100644
--- a/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
@@ -19,11 +19,11 @@
class RecentsAnimation;
-static Benchmark _Recents(BenchmarkInfo{
+static TestScene::Registrar _Recents(TestScene::Info{
"recents",
"A recents-like scrolling list of textures. "
"Consists of updating a texture every frame",
- simpleCreateScene<RecentsAnimation>
+ TestScene::simpleCreateScene<RecentsAnimation>
});
class RecentsAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
index a1f04d6..a9293ab 100644
--- a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
@@ -19,11 +19,11 @@
class RectGridAnimation;
-static Benchmark _RectGrid(BenchmarkInfo{
+static TestScene::Registrar _RectGrid(TestScene::Info{
"rectgrid",
"A dense grid of 1x1 rects that should visually look like a single rect. "
"Low CPU/GPU load.",
- simpleCreateScene<RectGridAnimation>
+ TestScene::simpleCreateScene<RectGridAnimation>
});
class RectGridAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index c73e97b..78fcd8b 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -18,11 +18,11 @@
class SaveLayerAnimation;
-static Benchmark _SaveLayer(BenchmarkInfo{
+static TestScene::Registrar _SaveLayer(TestScene::Info{
"savelayer",
"A nested pair of clipped saveLayer operations. "
"Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back again.",
- simpleCreateScene<SaveLayerAnimation>
+ TestScene::simpleCreateScene<SaveLayerAnimation>
});
class SaveLayerAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
index 26c86aa..d3249b8 100644
--- a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
@@ -18,11 +18,11 @@
class ShadowGrid2Animation;
-static Benchmark _ShadowGrid2(BenchmarkInfo{
+static TestScene::Registrar _ShadowGrid2(TestScene::Info{
"shadowgrid2",
"A dense grid of rounded rects that cast a shadow. This is a higher CPU load "
"variant of shadowgrid. Very high CPU load, high GPU load.",
- simpleCreateScene<ShadowGrid2Animation>
+ TestScene::simpleCreateScene<ShadowGrid2Animation>
});
class ShadowGrid2Animation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
index ee3c590..5ffedf0 100644
--- a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
@@ -18,11 +18,11 @@
class ShadowGridAnimation;
-static Benchmark _ShadowGrid(BenchmarkInfo{
+static TestScene::Registrar _ShadowGrid(TestScene::Info{
"shadowgrid",
"A grid of rounded rects that cast a shadow. Simplified scenario of an "
"Android TV-style launcher interface. High CPU/GPU load.",
- simpleCreateScene<ShadowGridAnimation>
+ TestScene::simpleCreateScene<ShadowGridAnimation>
});
class ShadowGridAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/TestSceneBase.h b/libs/hwui/tests/common/scenes/TestSceneBase.h
index 8a24149..ac78124 100644
--- a/libs/hwui/tests/common/scenes/TestSceneBase.h
+++ b/libs/hwui/tests/common/scenes/TestSceneBase.h
@@ -19,8 +19,7 @@
#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include "RenderNode.h"
-#include "tests/macrobench/Benchmark.h"
-#include "tests/macrobench/TestContext.h"
+#include "tests/common/TestContext.h"
#include "tests/common/TestScene.h"
#include "tests/common/TestUtils.h"
diff --git a/libs/hwui/tests/macrobench/Benchmark.h b/libs/hwui/tests/macrobench/Benchmark.h
deleted file mode 100644
index aad8eb3..0000000
--- a/libs/hwui/tests/macrobench/Benchmark.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-#ifndef TESTS_BENCHMARK_H
-#define TESTS_BENCHMARK_H
-
-#include "tests/common/TestScene.h"
-
-#include <string>
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-struct BenchmarkOptions {
- int count;
-};
-
-typedef test::TestScene* (*CreateScene)(const BenchmarkOptions&);
-
-template <class T>
-test::TestScene* simpleCreateScene(const BenchmarkOptions&) {
- return new T();
-}
-
-struct BenchmarkInfo {
- std::string name;
- std::string description;
- CreateScene createScene;
-};
-
-class Benchmark {
-public:
- Benchmark(const BenchmarkInfo& info) {
- registerBenchmark(info);
- }
-
-private:
- Benchmark() = delete;
- Benchmark(const Benchmark&) = delete;
- Benchmark& operator=(const Benchmark&) = delete;
-
- static void registerBenchmark(const BenchmarkInfo& info);
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* TESTS_BENCHMARK_H */
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 1e1c6a1..8261220 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -15,9 +15,9 @@
*/
#include "AnimationContext.h"
-#include "Benchmark.h"
#include "RenderNode.h"
-#include "TestContext.h"
+#include "tests/common/TestContext.h"
+#include "tests/common/TestScene.h"
#include "tests/common/scenes/TestSceneBase.h"
#include "renderthread/RenderProxy.h"
#include "renderthread/RenderTask.h"
@@ -38,7 +38,7 @@
}
};
-void run(const BenchmarkInfo& info, const BenchmarkOptions& opts) {
+void run(const TestScene::Info& info, const TestScene::Options& opts) {
// Switch to the real display
gDisplay = getBuiltInDisplay();
diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp
index 48566e8..619713c 100644
--- a/libs/hwui/tests/macrobench/main.cpp
+++ b/libs/hwui/tests/macrobench/main.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Benchmark.h"
+#include "tests/common/TestScene.h"
#include "protos/hwui.pb.h"
@@ -27,23 +27,13 @@
using namespace android;
using namespace android::uirenderer;
-
-// Not a static global because we need to force the map to be constructed
-// before we try to add things to it.
-std::unordered_map<std::string, BenchmarkInfo>& testMap() {
- static std::unordered_map<std::string, BenchmarkInfo> testMap;
- return testMap;
-}
-
-void Benchmark::registerBenchmark(const BenchmarkInfo& info) {
- testMap()[info.name] = info;
-}
+using namespace android::uirenderer::test;
static int gFrameCount = 150;
static int gRepeatCount = 1;
-static std::vector<BenchmarkInfo> gRunTests;
+static std::vector<TestScene::Info> gRunTests;
-void run(const BenchmarkInfo& info, const BenchmarkOptions& opts);
+void run(const TestScene::Info& info, const TestScene::Options& opts);
static void printHelp() {
printf("\
@@ -59,7 +49,7 @@
static void listTests() {
printf("Tests: \n");
- for (auto&& test : testMap()) {
+ for (auto&& test : TestScene::testMap()) {
auto&& info = test.second;
const char* col1 = info.name.c_str();
int dlen = info.description.length();
@@ -168,8 +158,8 @@
if (optind < argc) {
do {
const char* test = argv[optind++];
- auto pos = testMap().find(test);
- if (pos == testMap().end()) {
+ auto pos = TestScene::testMap().find(test);
+ if (pos == TestScene::testMap().end()) {
fprintf(stderr, "Unknown test '%s'\n", test);
exit(EXIT_FAILURE);
} else {
@@ -177,14 +167,14 @@
}
} while (optind < argc);
} else {
- gRunTests.push_back(testMap()["shadowgrid"]);
+ gRunTests.push_back(TestScene::testMap()["shadowgrid"]);
}
}
int main(int argc, char* argv[]) {
parseOptions(argc, argv);
- BenchmarkOptions opts;
+ TestScene::Options opts;
opts.count = gFrameCount;
for (int i = 0; i < gRepeatCount; i++) {
for (auto&& test : gRunTests) {
diff --git a/libs/hwui/tests/microbench/OpReordererBench.cpp b/libs/hwui/tests/microbench/OpReordererBench.cpp
index ac2b15c..6bfe5a9 100644
--- a/libs/hwui/tests/microbench/OpReordererBench.cpp
+++ b/libs/hwui/tests/microbench/OpReordererBench.cpp
@@ -23,6 +23,8 @@
#include "OpReorderer.h"
#include "RecordedOp.h"
#include "RecordingCanvas.h"
+#include "tests/common/TestContext.h"
+#include "tests/common/TestScene.h"
#include "tests/common/TestUtils.h"
#include "Vector.h"
#include "tests/microbench/MicroBench.h"
@@ -31,6 +33,8 @@
using namespace android;
using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::test;
const LayerUpdateQueue sEmptyLayerUpdateQueue;
const Vector3 sLightCenter = {100, 100, 100};
@@ -71,7 +75,7 @@
BENCHMARK_NO_ARG(BM_OpReorderer_deferAndRender);
void BM_OpReorderer_deferAndRender::Run(int iters) {
- TestUtils::runOnRenderThread([this, iters](renderthread::RenderThread& thread) {
+ TestUtils::runOnRenderThread([this, iters](RenderThread& thread) {
auto nodes = createTestNodeList();
BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 };
@@ -90,3 +94,67 @@
StopBenchmarkTiming();
});
}
+
+static std::vector<sp<RenderNode>> getSyncedSceneNodes(const char* sceneName) {
+ gDisplay = getBuiltInDisplay(); // switch to real display if present
+
+ TestContext testContext;
+ TestScene::Options opts;
+ std::unique_ptr<TestScene> scene(TestScene::testMap()[sceneName].createScene(opts));
+
+ sp<RenderNode> rootNode = TestUtils::createNode(0, 0, gDisplay.w, gDisplay.h,
+ [&scene](RenderProperties& props, TestCanvas& canvas) {
+ scene->createContent(gDisplay.w, gDisplay.h, canvas);
+ });
+
+ TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
+ std::vector<sp<RenderNode>> nodes;
+ nodes.emplace_back(rootNode);
+ return nodes;
+}
+
+static void benchDeferScene(testing::Benchmark& benchmark, int iters, const char* sceneName) {
+ auto nodes = getSyncedSceneNodes(sceneName);
+ benchmark.StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
+ nodes, sLightCenter);
+ MicroBench::DoNotOptimize(&reorderer);
+ }
+ benchmark.StopBenchmarkTiming();
+}
+
+static void benchDeferAndRenderScene(testing::Benchmark& benchmark,
+ int iters, const char* sceneName) {
+ TestUtils::runOnRenderThread([&benchmark, iters, sceneName](RenderThread& thread) {
+ auto nodes = getSyncedSceneNodes(sceneName);
+ BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 }; // TODO!
+
+ RenderState& renderState = thread.renderState();
+ Caches& caches = Caches::getInstance();
+
+ benchmark.StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
+ nodes, sLightCenter);
+
+ BakedOpRenderer renderer(caches, renderState, true, lightInfo);
+ reorderer.replayBakedOps<BakedOpDispatcher>(renderer);
+ MicroBench::DoNotOptimize(&renderer);
+ }
+ benchmark.StopBenchmarkTiming();
+ });
+}
+
+BENCHMARK_NO_ARG(BM_OpReorderer_listview_defer);
+void BM_OpReorderer_listview_defer::Run(int iters) {
+ benchDeferScene(*this, iters, "listview");
+}
+
+BENCHMARK_NO_ARG(BM_OpReorderer_listview_deferAndRender);
+void BM_OpReorderer_listview_deferAndRender::Run(int iters) {
+ benchDeferAndRenderScene(*this, iters, "listview");
+}
+