Refactor hwuitest
Yank animations out into their own files
Change-Id: Iea522ee032752019c07ff308c3a3993011054308
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 92226f5..0a57d50 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -30,6 +30,7 @@
utils/StringUtils.cpp \
utils/TestWindowContext.cpp \
utils/VectorDrawableUtils.cpp \
+ utils/TestUtils.cpp \
AmbientShadow.cpp \
AnimationContext.cpp \
Animator.cpp \
@@ -253,9 +254,11 @@
LOCAL_SRC_FILES += \
tests/TestContext.cpp \
- tests/TreeContentAnimation.cpp \
+ tests/TestSceneRunner.cpp \
tests/main.cpp
+LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/scenes)
+
include $(BUILD_EXECUTABLE)
# ------------------------
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index 7a62037..4be1f99 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -23,7 +23,7 @@
#include "DisplayListCanvas.h"
#endif
#include "microbench/MicroBench.h"
-#include "unit_tests/TestUtils.h"
+#include "utils/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/microbench/OpReordererBench.cpp b/libs/hwui/microbench/OpReordererBench.cpp
index b24858e..eea0c7f 100644
--- a/libs/hwui/microbench/OpReordererBench.cpp
+++ b/libs/hwui/microbench/OpReordererBench.cpp
@@ -21,7 +21,7 @@
#include "OpReorderer.h"
#include "RecordedOp.h"
#include "RecordingCanvas.h"
-#include "unit_tests/TestUtils.h"
+#include "utils/TestUtils.h"
#include "microbench/MicroBench.h"
#include <vector>
diff --git a/libs/hwui/tests/Benchmark.h b/libs/hwui/tests/Benchmark.h
index e16310e..3f87d7f 100644
--- a/libs/hwui/tests/Benchmark.h
+++ b/libs/hwui/tests/Benchmark.h
@@ -16,6 +16,8 @@
#ifndef TESTS_BENCHMARK_H
#define TESTS_BENCHMARK_H
+#include "TestScene.h"
+
#include <string>
#include <vector>
@@ -26,12 +28,17 @@
int count;
};
-typedef void (*BenchmarkFunctor)(const BenchmarkOptions&);
+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;
- BenchmarkFunctor functor;
+ CreateScene createScene;
};
class Benchmark {
diff --git a/libs/hwui/tests/TestScene.h b/libs/hwui/tests/TestScene.h
new file mode 100644
index 0000000..b5d8954
--- /dev/null
+++ b/libs/hwui/tests/TestScene.h
@@ -0,0 +1,44 @@
+/*
+ * 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_TESTSCENE_H
+#define TESTS_TESTSCENE_H
+
+namespace android {
+namespace uirenderer {
+class RenderNode;
+
+#if HWUI_NEW_OPS
+class RecordingCanvas;
+typedef RecordingCanvas TestCanvas;
+#else
+class DisplayListCanvas;
+typedef DisplayListCanvas TestCanvas;
+#endif
+
+namespace test {
+
+class TestScene {
+public:
+ virtual ~TestScene() {}
+ virtual void createContent(int width, int height, TestCanvas& renderer) = 0;
+ virtual void doFrame(int frameNr) = 0;
+};
+
+} // namespace test
+} // namespace uirenderer
+} // namespace android
+
+#endif /* TESTS_TESTSCENE_H */
diff --git a/libs/hwui/tests/TestSceneRunner.cpp b/libs/hwui/tests/TestSceneRunner.cpp
new file mode 100644
index 0000000..0376e10
--- /dev/null
+++ b/libs/hwui/tests/TestSceneRunner.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 "AnimationContext.h"
+#include "Benchmark.h"
+#include "RenderNode.h"
+#include "TestContext.h"
+#include "scenes/TestSceneBase.h"
+#include "renderthread/RenderProxy.h"
+#include "renderthread/RenderTask.h"
+
+#include <cutils/log.h>
+#include <gui/Surface.h>
+#include <ui/PixelFormat.h>
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::test;
+
+class ContextFactory : public IContextFactory {
+public:
+ virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
+ return new AnimationContext(clock);
+ }
+};
+
+void run(const BenchmarkInfo& info, const BenchmarkOptions& opts) {
+ // Switch to the real display
+ gDisplay = getBuiltInDisplay();
+
+ std::unique_ptr<TestScene> scene(info.createScene(opts));
+
+ TestContext testContext;
+
+ // create the native surface
+ const int width = gDisplay.w;
+ const int height = gDisplay.h;
+ sp<Surface> surface = testContext.surface();
+
+ sp<RenderNode> rootNode = TestUtils::createNode(0, 0, width, height,
+ [&scene, width, height](RenderProperties& props, TestCanvas& canvas) {
+ props.setClipToBounds(false);
+ scene->createContent(width, height, canvas);
+ });
+
+ ContextFactory factory;
+ std::unique_ptr<RenderProxy> proxy(new RenderProxy(false,
+ rootNode.get(), &factory));
+ proxy->loadSystemProperties();
+ proxy->initialize(surface);
+ float lightX = width / 2.0;
+ proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
+ proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+
+ // Do a few cold runs then reset the stats so that the caches are all hot
+ for (int i = 0; i < 3; i++) {
+ testContext.waitForVsync();
+ nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+ proxy->syncAndDrawFrame();
+ }
+ proxy->resetProfileInfo();
+
+ for (int i = 0; i < opts.count; i++) {
+ testContext.waitForVsync();
+
+ ATRACE_NAME("UI-Draw Frame");
+ nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+ scene->doFrame(i);
+ proxy->syncAndDrawFrame();
+ }
+
+ proxy->dumpProfileInfo(STDOUT_FILENO, 0);
+}
diff --git a/libs/hwui/tests/TreeContentAnimation.cpp b/libs/hwui/tests/TreeContentAnimation.cpp
deleted file mode 100644
index 81bf9ed..0000000
--- a/libs/hwui/tests/TreeContentAnimation.cpp
+++ /dev/null
@@ -1,428 +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.
- */
-
-#include <cutils/log.h>
-#include <gui/Surface.h>
-#include <ui/PixelFormat.h>
-
-#include <AnimationContext.h>
-#include <DisplayListCanvas.h>
-#include <RecordingCanvas.h>
-#include <RenderNode.h>
-#include <renderthread/RenderProxy.h>
-#include <renderthread/RenderTask.h>
-#include <unit_tests/TestUtils.h>
-
-#include "Benchmark.h"
-#include "TestContext.h"
-
-#include "protos/hwui.pb.h"
-
-#include <stdio.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <vector>
-
-using namespace android;
-using namespace android::uirenderer;
-using namespace android::uirenderer::renderthread;
-using namespace android::uirenderer::test;
-
-#if HWUI_NEW_OPS
-typedef RecordingCanvas TestCanvas;
-#else
-typedef DisplayListCanvas TestCanvas;
-#endif
-
-
-class ContextFactory : public IContextFactory {
-public:
- virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
- return new AnimationContext(clock);
- }
-};
-
-static void recordNode(RenderNode& node, std::function<void(TestCanvas&)> contentCallback) {
- TestCanvas canvas(node.stagingProperties().getWidth(), node.stagingProperties().getHeight());
- contentCallback(canvas);
- node.setStagingDisplayList(canvas.finishRecording());
-}
-
-class TreeContentAnimation {
-public:
- virtual ~TreeContentAnimation() {}
- int frameCount = 150;
- virtual int getFrameCount() { return frameCount; }
- virtual void setFrameCount(int fc) {
- if (fc > 0) {
- frameCount = fc;
- }
- }
- virtual void createContent(int width, int height, TestCanvas* canvas) = 0;
- virtual void doFrame(int frameNr) = 0;
-
- template <class T>
- static void run(const BenchmarkOptions& opts) {
- // Switch to the real display
- gDisplay = getBuiltInDisplay();
-
- T animation;
- animation.setFrameCount(opts.count);
-
- TestContext testContext;
-
- // create the native surface
- const int width = gDisplay.w;
- const int height = gDisplay.h;
- sp<Surface> surface = testContext.surface();
-
- RenderNode* rootNode = new RenderNode();
- rootNode->incStrong(nullptr);
- rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
- rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- rootNode->mutateStagingProperties().setClipToBounds(false);
- rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);
-
- ContextFactory factory;
- std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode, &factory));
- proxy->loadSystemProperties();
- proxy->initialize(surface);
- float lightX = width / 2.0;
- proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
- proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
-
- recordNode(*rootNode, [&animation, width, height](TestCanvas& canvas) {
- animation.createContent(width, height, &canvas); //TODO: no&
- });
-
- // Do a few cold runs then reset the stats so that the caches are all hot
- for (int i = 0; i < 3; i++) {
- testContext.waitForVsync();
- proxy->syncAndDrawFrame();
- }
- proxy->resetProfileInfo();
-
- for (int i = 0; i < animation.getFrameCount(); i++) {
- testContext.waitForVsync();
-
- ATRACE_NAME("UI-Draw Frame");
- nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
- UiFrameInfoBuilder(proxy->frameInfo())
- .setVsync(vsync, vsync);
- animation.doFrame(i);
- proxy->syncAndDrawFrame();
- }
-
- proxy->dumpProfileInfo(STDOUT_FILENO, 0);
- rootNode->decStrong(nullptr);
- }
-};
-
-class ShadowGridAnimation : public TreeContentAnimation {
-public:
- std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- canvas->insertReorderBarrier(true);
-
- for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
- for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
- sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
- canvas->drawRenderNode(card.get());
- cards.push_back(card);
- }
- }
-
- canvas->insertReorderBarrier(false);
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- for (size_t ci = 0; ci < cards.size(); ci++) {
- cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
- cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
- cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
- }
-private:
- sp<RenderNode> createCard(int x, int y, int width, int height) {
- sp<RenderNode> node = new RenderNode();
- node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
- node->mutateStagingProperties().setElevation(dp(16));
- node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
- node->mutateStagingProperties().mutableOutline().setShouldClip(true);
- node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
-
- recordNode(*node, [](TestCanvas& canvas) {
- canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
- });
- return node;
- }
-};
-static Benchmark _ShadowGrid(BenchmarkInfo{
- "shadowgrid",
- "A grid of rounded rects that cast a shadow. Simplified scenario of an "
- "Android TV-style launcher interface. High CPU/GPU load.",
- TreeContentAnimation::run<ShadowGridAnimation>
-});
-
-class ShadowGrid2Animation : public TreeContentAnimation {
-public:
- std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- canvas->insertReorderBarrier(true);
-
- for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
- for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
- sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
- canvas->drawRenderNode(card.get());
- cards.push_back(card);
- }
- }
-
- canvas->insertReorderBarrier(false);
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- for (size_t ci = 0; ci < cards.size(); ci++) {
- cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
- cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
- cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
- }
-private:
- sp<RenderNode> createCard(int x, int y, int width, int height) {
- sp<RenderNode> node = new RenderNode();
- node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
- node->mutateStagingProperties().setElevation(dp(16));
- node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
- node->mutateStagingProperties().mutableOutline().setShouldClip(true);
- node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
-
- recordNode(*node, [](TestCanvas& canvas) {
- canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
- });
- return node;
- }
-};
-static Benchmark _ShadowGrid2(BenchmarkInfo{
- "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.",
- TreeContentAnimation::run<ShadowGrid2Animation>
-});
-
-class RectGridAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card = new RenderNode();
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- canvas->insertReorderBarrier(true);
-
- card->mutateStagingProperties().setLeftTopRightBottom(50, 50, 250, 250);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- recordNode(*card, [](TestCanvas& canvas) {
- canvas.drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
-
- SkRegion region;
- for (int xOffset = 0; xOffset < 200; xOffset+=2) {
- for (int yOffset = 0; yOffset < 200; yOffset+=2) {
- region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op);
- }
- }
-
- SkPaint paint;
- paint.setColor(0xff00ffff);
- canvas.drawRegion(region, paint);
- });
- canvas->drawRenderNode(card.get());
-
- canvas->insertReorderBarrier(false);
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- card->mutateStagingProperties().setTranslationX(curFrame);
- card->mutateStagingProperties().setTranslationY(curFrame);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
-};
-static Benchmark _RectGrid(BenchmarkInfo{
- "rectgrid",
- "A dense grid of 1x1 rects that should visually look like a single rect. "
- "Low CPU/GPU load.",
- TreeContentAnimation::run<RectGridAnimation>
-});
-
-class OvalAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card = new RenderNode();
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- canvas->insertReorderBarrier(true);
-
- card->mutateStagingProperties().setLeftTopRightBottom(0, 0, 200, 200);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- recordNode(*card, [](TestCanvas& canvas) {
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(0xFF000000);
- canvas.drawOval(0, 0, 200, 200, paint);
- });
- canvas->drawRenderNode(card.get());
-
- canvas->insertReorderBarrier(false);
- }
-
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- card->mutateStagingProperties().setTranslationX(curFrame);
- card->mutateStagingProperties().setTranslationY(curFrame);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
-};
-static Benchmark _Oval(BenchmarkInfo{
- "oval",
- "Draws 1 oval.",
- TreeContentAnimation::run<OvalAnimation>
-});
-
-class PartialDamageTest : public TreeContentAnimation {
-public:
- std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, TestCanvas* canvas) override {
- static SkColor COLORS[] = {
- 0xFFF44336,
- 0xFF9C27B0,
- 0xFF2196F3,
- 0xFF4CAF50,
- };
-
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
-
- for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
- for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
- sp<RenderNode> card = createCard(x, y, dp(100), dp(100),
- COLORS[static_cast<int>((y / dp(116))) % 4]);
- canvas->drawRenderNode(card.get());
- cards.push_back(card);
- }
- }
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- cards[0]->mutateStagingProperties().setTranslationX(curFrame);
- cards[0]->mutateStagingProperties().setTranslationY(curFrame);
- cards[0]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
-
- recordNode(*cards[0], [curFrame](TestCanvas& canvas) {
- canvas.drawColor(interpolateColor(curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0),
- SkXfermode::kSrcOver_Mode);
- });
- }
-
- static SkColor interpolateColor(float fraction, SkColor start, SkColor end) {
- int startA = (start >> 24) & 0xff;
- int startR = (start >> 16) & 0xff;
- int startG = (start >> 8) & 0xff;
- int startB = start & 0xff;
-
- int endA = (end >> 24) & 0xff;
- int endR = (end >> 16) & 0xff;
- int endG = (end >> 8) & 0xff;
- int endB = end & 0xff;
-
- return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
- (int)((startR + (int)(fraction * (endR - startR))) << 16) |
- (int)((startG + (int)(fraction * (endG - startG))) << 8) |
- (int)((startB + (int)(fraction * (endB - startB))));
- }
-private:
- sp<RenderNode> createCard(int x, int y, int width, int height, SkColor color) {
- sp<RenderNode> node = new RenderNode();
- node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
- node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
-
- recordNode(*node, [color](TestCanvas& canvas) {
- canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
- });
- return node;
- }
-};
-static Benchmark _PartialDamage(BenchmarkInfo{
- "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.",
- TreeContentAnimation::run<PartialDamageTest>
-});
-
-
-class SaveLayerAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card = new RenderNode();
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
-
- card->mutateStagingProperties().setLeftTopRightBottom(0, 0, 200, 200);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- recordNode(*card, [](TestCanvas& canvas) {
- canvas.saveLayerAlpha(0, 0, 200, 200, 128, SkCanvas::kClipToLayer_SaveFlag);
- canvas.drawColor(0xFF00FF00, SkXfermode::kSrcOver_Mode); // outer, unclipped
- canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag);
- canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode); // inner, clipped
- canvas.restore();
- canvas.restore();
- });
-
- canvas->drawRenderNode(card.get());
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- card->mutateStagingProperties().setTranslationX(curFrame);
- card->mutateStagingProperties().setTranslationY(curFrame);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
-};
-static Benchmark _SaveLayer(BenchmarkInfo{
- "savelayer",
- "A nested pair of clipped saveLayer operations. "
- "Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back again.",
- TreeContentAnimation::run<SaveLayerAnimation>
-});
-
-
-class HwLayerAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card = TestUtils::createNode<TestCanvas>(0, 0, 200, 200, [] (TestCanvas& canvas) {
- canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode);
- }, TestUtils::getHwLayerSetupCallback());
- void createContent(int width, int height, TestCanvas* canvas) override {
- canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
- canvas->drawRenderNode(card.get());
- }
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- card->mutateStagingProperties().setTranslationX(curFrame);
- card->mutateStagingProperties().setTranslationY(curFrame);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
-};
-static Benchmark _HwLayer(BenchmarkInfo{
- "hwlayer",
- "A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
- "Tests the hardware layer codepath.",
- TreeContentAnimation::run<HwLayerAnimation>
-});
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index aee84de..48566e8 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -43,6 +43,8 @@
static int gRepeatCount = 1;
static std::vector<BenchmarkInfo> gRunTests;
+void run(const BenchmarkInfo& info, const BenchmarkOptions& opts);
+
static void printHelp() {
printf("\
USAGE: hwuitest [OPTIONS] <TESTNAME>\n\
@@ -186,7 +188,7 @@
opts.count = gFrameCount;
for (int i = 0; i < gRepeatCount; i++) {
for (auto&& test : gRunTests) {
- test.functor(opts);
+ run(test, opts);
}
}
printf("Success!\n");
diff --git a/libs/hwui/tests/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/scenes/HwLayerAnimation.cpp
new file mode 100644
index 0000000..e316eca
--- /dev/null
+++ b/libs/hwui/tests/scenes/HwLayerAnimation.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+class HwLayerAnimation;
+
+static Benchmark _HwLayer(BenchmarkInfo{
+ "hwlayer",
+ "A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
+ "Tests the hardware layer codepath.",
+ simpleCreateScene<HwLayerAnimation>
+});
+
+class HwLayerAnimation : public TestScene {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ card = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& props, TestCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode);
+ });
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
+ canvas.drawRenderNode(card.get());
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+};
diff --git a/libs/hwui/tests/scenes/OvalAnimation.cpp b/libs/hwui/tests/scenes/OvalAnimation.cpp
new file mode 100644
index 0000000..919a53d
--- /dev/null
+++ b/libs/hwui/tests/scenes/OvalAnimation.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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"
+
+class OvalAnimation;
+
+static Benchmark _Oval(BenchmarkInfo{
+ "oval",
+ "Draws 1 oval.",
+ simpleCreateScene<OvalAnimation>
+});
+
+class OvalAnimation : public TestScene {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ canvas.insertReorderBarrier(true);
+
+ card = TestUtils::createNode(0, 0, 200, 200, [](TestCanvas& canvas) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(0xFF000000);
+ canvas.drawOval(0, 0, 200, 200, paint);
+ });
+
+ canvas.drawRenderNode(card.get());
+ canvas.insertReorderBarrier(false);
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+};
diff --git a/libs/hwui/tests/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/scenes/PartialDamageAnimation.cpp
new file mode 100644
index 0000000..0fba4eb
--- /dev/null
+++ b/libs/hwui/tests/scenes/PartialDamageAnimation.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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"
+
+class PartialDamageAnimation;
+
+static Benchmark _PartialDamage(BenchmarkInfo{
+ "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>
+});
+
+class PartialDamageAnimation : public TestScene {
+public:
+ std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ static SkColor COLORS[] = {
+ 0xFFF44336,
+ 0xFF9C27B0,
+ 0xFF2196F3,
+ 0xFF4CAF50,
+ };
+
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+
+ for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
+ for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
+ SkColor color = COLORS[static_cast<int>((y / dp(116))) % 4];
+ sp<RenderNode> card = TestUtils::createNode(x, y,
+ x + dp(100), y + dp(100),
+ [color](TestCanvas& canvas) {
+ canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
+ });
+ canvas.drawRenderNode(card.get());
+ cards.push_back(card);
+ }
+ }
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ cards[0]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[0]->mutateStagingProperties().setTranslationY(curFrame);
+ cards[0]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+ TestUtils::recordNode(*cards[0], [curFrame](TestCanvas& canvas) {
+ SkColor color = TestUtils::interpolateColor(
+ curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0);
+ canvas.drawColor(color, SkXfermode::kSrcOver_Mode);
+ });
+ }
+};
diff --git a/libs/hwui/tests/scenes/RecentsAnimation.cpp b/libs/hwui/tests/scenes/RecentsAnimation.cpp
new file mode 100644
index 0000000..1e38d84
--- /dev/null
+++ b/libs/hwui/tests/scenes/RecentsAnimation.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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"
+
+class RecentsAnimation;
+
+static Benchmark _Recents(BenchmarkInfo{
+ "recents",
+ "A recents-like scrolling list of textures. "
+ "Consists of updating a texture every frame",
+ simpleCreateScene<RecentsAnimation>
+});
+
+class RecentsAnimation : public TestScene {
+public:
+ void createContent(int width, int height, TestCanvas& renderer) override {
+ static SkColor COLORS[] = {
+ 0xFFF44336,
+ 0xFF9C27B0,
+ 0xFF2196F3,
+ 0xFF4CAF50,
+ };
+
+ thumbnailSize = std::min(std::min(width, height) / 2, 720);
+ int cardsize = std::min(width, height) - dp(64);
+
+ renderer.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ renderer.insertReorderBarrier(true);
+
+ int x = dp(32);
+ for (int i = 0; i < 4; i++) {
+ int y = (height / 4) * i;
+ SkBitmap thumb = TestUtils::createSkBitmap(thumbnailSize, thumbnailSize);
+ thumb.eraseColor(COLORS[i]);
+ sp<RenderNode> card = createCard(x, y, cardsize, cardsize, thumb);
+ card->mutateStagingProperties().setElevation(i * dp(8));
+ renderer.drawRenderNode(card.get());
+ mThumbnail = thumb;
+ mCards.push_back(card);
+ }
+
+ renderer.insertReorderBarrier(false);
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ for (size_t ci = 0; ci < mCards.size(); ci++) {
+ mCards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+ mCards[ci]->setPropertyFieldsDirty(RenderNode::Y);
+ }
+ mThumbnail.eraseColor(TestUtils::interpolateColor(
+ curFrame / 150.0f, 0xFF4CAF50, 0xFFFF5722));
+ }
+
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height,
+ const SkBitmap& thumb) {
+ return TestUtils::createNode(x, y, x + width, y + height,
+ [&thumb, width, height](RenderProperties& props, TestCanvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
+ props.mutableOutline().setShouldClip(true);
+
+ canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+ canvas.drawBitmap(thumb, 0, 0, thumb.width(), thumb.height(),
+ 0, 0, width, height, nullptr);
+ });
+ }
+
+ SkBitmap mThumbnail;
+ std::vector< sp<RenderNode> > mCards;
+ int thumbnailSize;
+};
diff --git a/libs/hwui/tests/scenes/RectGridAnimation.cpp b/libs/hwui/tests/scenes/RectGridAnimation.cpp
new file mode 100644
index 0000000..254f828
--- /dev/null
+++ b/libs/hwui/tests/scenes/RectGridAnimation.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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"
+
+class RectGridAnimation;
+
+static Benchmark _RectGrid(BenchmarkInfo{
+ "rectgrid",
+ "A dense grid of 1x1 rects that should visually look like a single rect. "
+ "Low CPU/GPU load.",
+ simpleCreateScene<RectGridAnimation>
+});
+
+class RectGridAnimation : public TestScene {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ canvas.insertReorderBarrier(true);
+
+ card = TestUtils::createNode(50, 50, 250, 250,
+ [](TestCanvas& canvas) {
+ canvas.drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
+
+ SkRegion region;
+ for (int xOffset = 0; xOffset < 200; xOffset+=2) {
+ for (int yOffset = 0; yOffset < 200; yOffset+=2) {
+ region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op);
+ }
+ }
+
+ SkPaint paint;
+ paint.setColor(0xff00ffff);
+ canvas.drawRegion(region, paint);
+ });
+ canvas.drawRenderNode(card.get());
+
+ canvas.insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+};
diff --git a/libs/hwui/tests/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/scenes/SaveLayerAnimation.cpp
new file mode 100644
index 0000000..c62dd19
--- /dev/null
+++ b/libs/hwui/tests/scenes/SaveLayerAnimation.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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"
+
+class SaveLayerAnimation;
+
+static Benchmark _SaveLayer(BenchmarkInfo{
+ "savelayer",
+ "A nested pair of clipped saveLayer operations. "
+ "Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back again.",
+ simpleCreateScene<SaveLayerAnimation>
+});
+
+class SaveLayerAnimation : public TestScene {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
+
+ card = TestUtils::createNode(0, 0, 200, 200,
+ [](TestCanvas& canvas) {
+ canvas.saveLayerAlpha(0, 0, 200, 200, 128, SkCanvas::kClipToLayer_SaveFlag);
+ canvas.drawColor(0xFF00FF00, SkXfermode::kSrcOver_Mode); // outer, unclipped
+ canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag);
+ canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode); // inner, clipped
+ canvas.restore();
+ canvas.restore();
+ });
+
+ canvas.drawRenderNode(card.get());
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+};
diff --git a/libs/hwui/tests/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/scenes/ShadowGrid2Animation.cpp
new file mode 100644
index 0000000..26c86aa
--- /dev/null
+++ b/libs/hwui/tests/scenes/ShadowGrid2Animation.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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"
+
+class ShadowGrid2Animation;
+
+static Benchmark _ShadowGrid2(BenchmarkInfo{
+ "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>
+});
+
+class ShadowGrid2Animation : public TestScene {
+public:
+ std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ canvas.insertReorderBarrier(true);
+
+ for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
+ for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
+ sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
+ canvas.drawRenderNode(card.get());
+ cards.push_back(card);
+ }
+ }
+
+ canvas.insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ for (size_t ci = 0; ci < cards.size(); ci++) {
+ cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+ cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ return TestUtils::createNode(x, y, x + width, y + height,
+ [width, height](RenderProperties& props, TestCanvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
+ props.mutableOutline().setShouldClip(true);
+ canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+ });
+ }
+};
diff --git a/libs/hwui/tests/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/scenes/ShadowGridAnimation.cpp
new file mode 100644
index 0000000..ee3c590
--- /dev/null
+++ b/libs/hwui/tests/scenes/ShadowGridAnimation.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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"
+
+class ShadowGridAnimation;
+
+static Benchmark _ShadowGrid(BenchmarkInfo{
+ "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>
+});
+
+class ShadowGridAnimation : public TestScene {
+public:
+ std::vector< sp<RenderNode> > cards;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
+ canvas.insertReorderBarrier(true);
+
+ for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
+ for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
+ sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
+ canvas.drawRenderNode(card.get());
+ cards.push_back(card);
+ }
+ }
+
+ canvas.insertReorderBarrier(false);
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ for (size_t ci = 0; ci < cards.size(); ci++) {
+ cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
+ cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
+ cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ return TestUtils::createNode(x, y, x + width, y + height,
+ [width, height](RenderProperties& props, TestCanvas& canvas) {
+ props.setElevation(dp(16));
+ props.mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
+ props.mutableOutline().setShouldClip(true);
+ canvas.drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
+ });
+ }
+};
diff --git a/libs/hwui/tests/scenes/TestSceneBase.h b/libs/hwui/tests/scenes/TestSceneBase.h
new file mode 100644
index 0000000..a208509
--- /dev/null
+++ b/libs/hwui/tests/scenes/TestSceneBase.h
@@ -0,0 +1,34 @@
+/*
+ * 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_SCENES_TESTSCENEBASE_H
+#define TESTS_SCENES_TESTSCENEBASE_H
+
+#include "DisplayListCanvas.h"
+#include "RecordingCanvas.h"
+#include "RenderNode.h"
+#include "tests/Benchmark.h"
+#include "tests/TestContext.h"
+#include "tests/TestScene.h"
+#include "utils/TestUtils.h"
+
+#include <functional>
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::test;
+
+#endif /* TESTS_SCENES_TESTSCENEBASE_H_ */
diff --git a/libs/hwui/unit_tests/BakedOpStateTests.cpp b/libs/hwui/unit_tests/BakedOpStateTests.cpp
index 4e00fb3..7ad2f9b 100644
--- a/libs/hwui/unit_tests/BakedOpStateTests.cpp
+++ b/libs/hwui/unit_tests/BakedOpStateTests.cpp
@@ -18,7 +18,7 @@
#include <BakedOpState.h>
#include <RecordedOp.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/unit_tests/FatVectorTests.cpp b/libs/hwui/unit_tests/FatVectorTests.cpp
index 3ef329a..c6ccf4d 100644
--- a/libs/hwui/unit_tests/FatVectorTests.cpp
+++ b/libs/hwui/unit_tests/FatVectorTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <utils/FatVector.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp b/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
index ef205ec..05fd08a 100644
--- a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
@@ -19,7 +19,7 @@
#include <LayerUpdateQueue.h>
#include <RenderNode.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/unit_tests/LinearAllocatorTests.cpp b/libs/hwui/unit_tests/LinearAllocatorTests.cpp
index 0f6b249..0591db6 100644
--- a/libs/hwui/unit_tests/LinearAllocatorTests.cpp
+++ b/libs/hwui/unit_tests/LinearAllocatorTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <utils/LinearAllocator.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp b/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
index ba92157..de86aed 100644
--- a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <renderstate/OffscreenBufferPool.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
index 07a1855..ec8048d 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -21,7 +21,7 @@
#include <OpReorderer.h>
#include <RecordedOp.h>
#include <RecordingCanvas.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
#include <unordered_map>
@@ -186,14 +186,14 @@
}
};
- sp<RenderNode> child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, [](RecordingCanvas& canvas) {
+ sp<RenderNode> child = TestUtils::createNode(10, 10, 110, 110, [](RecordingCanvas& canvas) {
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 100, 100, paint);
});
RenderNode* childPtr = child.get();
- sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [childPtr](RecordingCanvas& canvas) {
+ sp<RenderNode> parent = TestUtils::createNode(0, 0, 200, 200, [childPtr](RecordingCanvas& canvas) {
SkPaint paint;
paint.setColor(SK_ColorDKGRAY);
canvas.drawRect(0, 0, 200, 200, paint);
@@ -221,7 +221,7 @@
}
};
- sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RecordingCanvas& canvas) {
+ sp<RenderNode> node = TestUtils::createNode(0, 0, 200, 200, [](RecordingCanvas& canvas) {
SkBitmap bitmap = TestUtils::createSkBitmap(200, 200);
canvas.drawBitmap(bitmap, 0, 0, nullptr);
});
@@ -396,11 +396,13 @@
}
};
- sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, [](RecordingCanvas& canvas) {
+ sp<RenderNode> node = TestUtils::createNode(10, 10, 110, 110,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 100, 100, paint);
- }, TestUtils::getHwLayerSetupCallback());
+ });
OffscreenBuffer** layerHandle = node->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would
@@ -483,18 +485,20 @@
}
};
- auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150,
- [](RecordingCanvas& canvas) {
+ auto child = TestUtils::createNode(50, 50, 150, 150,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 100, 100, paint);
- }, TestUtils::getHwLayerSetupCallback());
+ });
OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100);
*(child->getLayerHandle()) = &childLayer;
RenderNode* childPtr = child.get();
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
- [childPtr](RecordingCanvas& canvas) {
+ auto parent = TestUtils::createNode(0, 0, 200, 200,
+ [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
SkPaint paint;
paint.setColor(SK_ColorDKGRAY);
canvas.drawRect(0, 0, 200, 200, paint);
@@ -502,7 +506,7 @@
canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag);
canvas.drawRenderNode(childPtr);
canvas.restore();
- }, TestUtils::getHwLayerSetupCallback());
+ });
OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200);
*(parent->getLayerHandle()) = &parentLayer;
@@ -529,7 +533,7 @@
canvas->drawRect(0, 0, 100, 100, paint);
}
static void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) {
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+ auto node = TestUtils::createNode(0, 0, 100, 100,
[expectedDrawOrder](RecordingCanvas& canvas) {
drawOrderedRect(&canvas, expectedDrawOrder);
});
@@ -546,7 +550,7 @@
}
};
- auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+ auto parent = TestUtils::createNode(0, 0, 100, 100,
[](RecordingCanvas& canvas) {
drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
drawOrderedRect(&canvas, 1);
@@ -570,15 +574,13 @@
// creates a 100x100 shadow casting node with provided translationZ
static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
- return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
- [](RecordingCanvas& canvas) {
+ return TestUtils::createNode(0, 0, 100, 100,
+ [translationZ] (RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setTranslationZ(translationZ);
+ properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 100, 100, paint);
- }, [translationZ] (RenderProperties& properties) {
- properties.setTranslationZ(translationZ);
- properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
- return RenderNode::GENERIC | RenderNode::TRANSLATION_Z;
});
}
@@ -600,7 +602,7 @@
}
};
- sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
+ sp<RenderNode> parent = TestUtils::createNode(0, 0, 200, 200,
[] (RecordingCanvas& canvas) {
canvas.insertReorderBarrier(true);
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
@@ -636,7 +638,7 @@
}
};
- sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
+ sp<RenderNode> parent = TestUtils::createNode(0, 0, 200, 200,
[] (RecordingCanvas& canvas) {
// save/restore outside of reorderBarrier, so they don't get moved out of place
canvas.translate(20, 10);
@@ -676,14 +678,15 @@
}
};
- sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160,
- [] (RecordingCanvas& canvas) {
+ sp<RenderNode> parent = TestUtils::createNode(50, 60, 150, 160,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ props.mutateLayerProperties().setType(LayerType::RenderLayer);
canvas.insertReorderBarrier(true);
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
canvas.translate(20, 10);
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
canvas.restore();
- }, TestUtils::getHwLayerSetupCallback());
+ });
OffscreenBuffer** layerHandle = parent->getLayerHandle();
// create RenderNode's layer here in same way prepareTree would, setting windowTransform
@@ -718,7 +721,7 @@
EXPECT_TRUE(index == 2 || index == 3);
}
};
- sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
+ sp<RenderNode> parent = TestUtils::createNode(0, 0, 200, 200,
[] (RecordingCanvas& canvas) {
canvas.insertReorderBarrier(true);
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
@@ -732,7 +735,7 @@
EXPECT_EQ(4, renderer.getIndex());
}
-static void testProperty(TestUtils::PropSetupCallback propSetupCallback,
+static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
class PropertyTestRenderer : public TestRendererBase {
public:
@@ -745,11 +748,13 @@
std::function<void(const RectOp&, const BakedOpState&)> mCallback;
};
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, [](RecordingCanvas& canvas) {
+ auto node = TestUtils::createNode(0, 0, 100, 100,
+ [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) {
+ propSetupCallback(props);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 100, 100, paint);
- }, propSetupCallback);
+ });
OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
createSyncedNodeList(node), sLightCenter);
@@ -762,7 +767,6 @@
testProperty([](RenderProperties& properties) {
properties.setAlpha(0.5f);
properties.setHasOverlappingRendering(false);
- return RenderNode::ALPHA | RenderNode::GENERIC;
}, [](const RectOp& op, const BakedOpState& state) {
EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op";
});
@@ -772,7 +776,6 @@
testProperty([](RenderProperties& properties) {
properties.setClipToBounds(true);
properties.setClipBounds(Rect(10, 20, 300, 400));
- return RenderNode::GENERIC;
}, [](const RectOp& op, const BakedOpState& state) {
EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds)
<< "Clip rect should be intersection of node bounds and clip bounds";
@@ -782,7 +785,6 @@
TEST(OpReorderer, renderPropRevealClip) {
testProperty([](RenderProperties& properties) {
properties.mutableRevealClip().set(true, 50, 50, 25);
- return RenderNode::GENERIC;
}, [](const RectOp& op, const BakedOpState& state) {
ASSERT_NE(nullptr, state.roundRectClipState);
EXPECT_TRUE(state.roundRectClipState->highPriority);
@@ -795,7 +797,6 @@
testProperty([](RenderProperties& properties) {
properties.mutableOutline().setShouldClip(true);
properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
- return RenderNode::GENERIC;
}, [](const RectOp& op, const BakedOpState& state) {
ASSERT_NE(nullptr, state.roundRectClipState);
EXPECT_FALSE(state.roundRectClipState->highPriority);
@@ -819,9 +820,6 @@
properties.setTranslationY(20);
properties.setScaleX(0.5f);
properties.setScaleY(0.7f);
- return RenderNode::GENERIC
- | RenderNode::TRANSLATION_X | RenderNode::TRANSLATION_Y
- | RenderNode::SCALE_X | RenderNode::SCALE_Y;
}, [](const RectOp& op, const BakedOpState& state) {
Matrix4 matrix;
matrix.loadTranslate(10, 10, 0); // left, top
@@ -857,7 +855,7 @@
* (for efficiency, and to fit in layer size constraints) based on parent clip.
*/
void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
- TestUtils::PropSetupCallback propSetupCallback) {
+ std::function<void(RenderProperties&)> propSetupCallback) {
class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
public:
SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
@@ -887,17 +885,16 @@
ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize())
<< "Node must be bigger than max texture size to exercise saveLayer codepath";
- auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000, [](RecordingCanvas& canvas) {
+ auto node = TestUtils::createNode(0, 0, 10000, 10000,
+ [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setHasOverlappingRendering(true);
+ properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
+ // apply other properties
+ propSetupCallback(properties);
+
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas.drawRect(0, 0, 10000, 10000, paint);
- }, [&propSetupCallback](RenderProperties& properties) {
- properties.setHasOverlappingRendering(true);
- properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
-
- // apply other properties
- int flags = propSetupCallback(properties);
- return RenderNode::GENERIC | RenderNode::ALPHA | flags;
});
auto nodes = createSyncedNodeList(node); // sync before querying height
@@ -914,7 +911,6 @@
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
properties.setTranslationX(10); // offset rendering content
properties.setTranslationY(-2000); // offset rendering content
- return RenderNode::TRANSLATION_X | RenderNode::TRANSLATION_Y;
});
EXPECT_EQ(190u, observedData.layerWidth);
EXPECT_EQ(200u, observedData.layerHeight);
@@ -937,9 +933,6 @@
properties.setPivotX(0);
properties.setPivotY(0);
properties.setRotation(45);
- return RenderNode::GENERIC
- | RenderNode::TRANSLATION_X | RenderNode::TRANSLATION_Y
- | RenderNode::ROTATION;
});
// ceil(sqrt(2) / 2 * 200) = 142
EXPECT_EQ(142u, observedData.layerWidth);
@@ -955,7 +948,6 @@
properties.setPivotY(0);
properties.setScaleX(2);
properties.setScaleY(0.5f);
- return RenderNode::GENERIC | RenderNode::SCALE_X | RenderNode::SCALE_Y;
});
EXPECT_EQ(100u, observedData.layerWidth);
EXPECT_EQ(400u, observedData.layerHeight);
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
index 83b37ab..22190f5 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -18,7 +18,7 @@
#include <RecordedOp.h>
#include <RecordingCanvas.h>
-#include <unit_tests/TestUtils.h>
+#include <utils/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/utils/TestUtils.cpp b/libs/hwui/utils/TestUtils.cpp
new file mode 100644
index 0000000..84230a7
--- /dev/null
+++ b/libs/hwui/utils/TestUtils.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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 "TestUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+SkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) {
+ int startA = (start >> 24) & 0xff;
+ int startR = (start >> 16) & 0xff;
+ int startG = (start >> 8) & 0xff;
+ int startB = start & 0xff;
+
+ int endA = (end >> 24) & 0xff;
+ int endR = (end >> 16) & 0xff;
+ int endG = (end >> 8) & 0xff;
+ int endB = end & 0xff;
+
+ return (int)((startA + (int)(fraction * (endA - startA))) << 24)
+ | (int)((startR + (int)(fraction * (endR - startR))) << 16)
+ | (int)((startG + (int)(fraction * (endG - startG))) << 8)
+ | (int)((startB + (int)(fraction * (endB - startB))));
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/unit_tests/TestUtils.h b/libs/hwui/utils/TestUtils.h
similarity index 76%
rename from libs/hwui/unit_tests/TestUtils.h
rename to libs/hwui/utils/TestUtils.h
index 38bafd5..f7f4f2d 100644
--- a/libs/hwui/unit_tests/TestUtils.h
+++ b/libs/hwui/utils/TestUtils.h
@@ -27,8 +27,10 @@
#if HWUI_NEW_OPS
#include <RecordedOp.h>
+#include <RecordingCanvas.h>
#else
#include <DisplayListOp.h>
+#include <DisplayListCanvas.h>
#endif
#include <memory>
@@ -36,6 +38,12 @@
namespace android {
namespace uirenderer {
+#if HWUI_NEW_OPS
+typedef RecordingCanvas TestCanvas;
+#else
+typedef DisplayListCanvas TestCanvas;
+#endif
+
#define EXPECT_MATRIX_APPROX_EQ(a, b) \
EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
@@ -97,7 +105,8 @@
static SkBitmap createSkBitmap(int width, int height) {
SkBitmap bitmap;
- SkImageInfo info = SkImageInfo::MakeUnknown(width, height);
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ kN32_SkColorType, kPremul_SkAlphaType);
bitmap.setInfo(info);
bitmap.allocPixels(info);
return bitmap;
@@ -111,18 +120,8 @@
return std::unique_ptr<DisplayList>(canvas.finishRecording());
}
- typedef std::function<int(RenderProperties&)> PropSetupCallback;
-
- static PropSetupCallback getHwLayerSetupCallback() {
- static PropSetupCallback sLayerSetupCallback = [] (RenderProperties& properties) {
- properties.mutateLayerProperties().setType(LayerType::RenderLayer);
- return RenderNode::GENERIC;
- };
- return sLayerSetupCallback;
- }
-
static sp<RenderNode> createNode(int left, int top, int right, int bottom,
- PropSetupCallback propSetupCallback = nullptr) {
+ std::function<void(RenderProperties& props, TestCanvas& canvas)> setup = nullptr) {
#if HWUI_NULL_GPU
// if RenderNodes are being sync'd/used, device info will be needed, since
// DeviceInfo::maxTextureSize() affects layer property
@@ -130,25 +129,39 @@
#endif
sp<RenderNode> node = new RenderNode();
- node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
- node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- if (propSetupCallback) {
- node->setPropertyFieldsDirty(propSetupCallback(node->mutateStagingProperties()));
+ RenderProperties& props = node->mutateStagingProperties();
+ props.setLeftTopRightBottom(left, top, right, bottom);
+ if (setup) {
+ TestCanvas canvas(props.getWidth(), props.getHeight());
+ setup(props, canvas);
+ node->setStagingDisplayList(canvas.finishRecording());
}
+ node->setPropertyFieldsDirty(0xFFFFFFFF);
return node;
}
- template<class CanvasType>
static sp<RenderNode> createNode(int left, int top, int right, int bottom,
- std::function<void(CanvasType& canvas)> canvasCallback,
- PropSetupCallback propSetupCallback = nullptr) {
- sp<RenderNode> node = createNode(left, top, right, bottom, propSetupCallback);
+ std::function<void(RenderProperties& props)> setup) {
+ return createNode(left, top, right, bottom,
+ [&setup](RenderProperties& props, TestCanvas& canvas) {
+ setup(props);
+ });
+ }
- auto&& props = node->stagingProperties(); // staging, since not sync'd yet
- CanvasType canvas(props.getWidth(), props.getHeight());
- canvasCallback(canvas);
- node->setStagingDisplayList(canvas.finishRecording());
- return node;
+ static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+ std::function<void(TestCanvas& canvas)> setup) {
+ return createNode(left, top, right, bottom,
+ [&setup](RenderProperties& props, TestCanvas& canvas) {
+ setup(canvas);
+ });
+ }
+
+ static void recordNode(RenderNode& node,
+ std::function<void(TestCanvas&)> contentCallback) {
+ TestCanvas canvas(node.stagingProperties().getWidth(),
+ node.stagingProperties().getHeight());
+ contentCallback(canvas);
+ node.setStagingDisplayList(canvas.finishRecording());
}
static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) {
@@ -180,6 +193,9 @@
TestTask task(rtCallback);
renderthread::RenderThread::getInstance().queueAndWait(&task);
}
+
+ static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
+
private:
static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
node->syncProperties();