summaryrefslogtreecommitdiff
path: root/libs/hwui/tests/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/tests/main.cpp')
-rw-r--r--libs/hwui/tests/main.cpp422
1 files changed, 138 insertions, 284 deletions
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 80d7029857c4..aee84de3ae7b 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -14,327 +14,181 @@
* limitations under the License.
*/
-#include <cutils/log.h>
-#include <gui/Surface.h>
-#include <ui/PixelFormat.h>
+#include "Benchmark.h"
-#include <AnimationContext.h>
-#include <DisplayListCanvas.h>
-#include <RenderNode.h>
-#include <renderthread/RenderProxy.h>
-#include <renderthread/RenderTask.h>
-
-#include "TestContext.h"
+#include "protos/hwui.pb.h"
+#include <getopt.h>
#include <stdio.h>
+#include <string>
#include <unistd.h>
+#include <unordered_map>
+#include <vector>
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);
- }
-};
-static DisplayListCanvas* startRecording(RenderNode* node) {
- DisplayListCanvas* renderer = new DisplayListCanvas();
- renderer->setViewport(node->stagingProperties().getWidth(),
- node->stagingProperties().getHeight());
- renderer->prepare();
- return renderer;
+// 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;
}
-static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
- renderer->finish();
- node->setStagingDisplayList(renderer->finishRecording());
- delete renderer;
+void Benchmark::registerBenchmark(const BenchmarkInfo& info) {
+ testMap()[info.name] = info;
}
-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, DisplayListCanvas* renderer) = 0;
- virtual void doFrame(int frameNr) = 0;
-
- template <class T>
- static void run(int frameCount) {
- T animation;
- animation.setFrameCount(frameCount);
-
- 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)});
-
- android::uirenderer::Rect DUMMY;
-
- DisplayListCanvas* renderer = startRecording(rootNode);
- animation.createContent(width, height, renderer);
- endRecording(renderer, rootNode);
-
- // 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, DisplayListCanvas* renderer) override {
- renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- renderer->insertReorderBarrier(true);
+static int gFrameCount = 150;
+static int gRepeatCount = 1;
+static std::vector<BenchmarkInfo> gRunTests;
+
+static void printHelp() {
+ printf("\
+USAGE: hwuitest [OPTIONS] <TESTNAME>\n\
+\n\
+OPTIONS:\n\
+ -c, --count=NUM NUM loops a test should run (example, number of frames)\n\
+ -r, --runs=NUM Repeat the test(s) NUM times\n\
+ -h, --help Display this help\n\
+ --list List all tests\n\
+\n");
+}
- 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));
- renderer->drawRenderNode(card.get());
- cards.push_back(card);
+static void listTests() {
+ printf("Tests: \n");
+ for (auto&& test : testMap()) {
+ auto&& info = test.second;
+ const char* col1 = info.name.c_str();
+ int dlen = info.description.length();
+ const char* col2 = info.description.c_str();
+ // World's best line breaking algorithm.
+ do {
+ int toPrint = dlen;
+ if (toPrint > 50) {
+ char* found = (char*) memrchr(col2, ' ', 50);
+ if (found) {
+ toPrint = found - col2;
+ } else {
+ toPrint = 50;
+ }
}
- }
-
- renderer->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);
- }
+ printf("%-20s %.*s\n", col1, toPrint, col2);
+ col1 = "";
+ col2 += toPrint;
+ dlen -= toPrint;
+ while (*col2 == ' ') {
+ col2++; dlen--;
+ }
+ } while (dlen > 0);
+ printf("\n");
}
-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);
+}
- DisplayListCanvas* renderer = startRecording(node.get());
- renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
- endRecording(renderer, node.get());
- return node;
- }
+static const struct option LONG_OPTIONS[] = {
+ { "frames", required_argument, nullptr, 'f' },
+ { "repeat", required_argument, nullptr, 'r' },
+ { "help", no_argument, nullptr, 'h' },
+ { "list", no_argument, nullptr, 'l' },
+ { 0, 0, 0, 0 }
};
-class ShadowGrid2Animation : public TreeContentAnimation {
-public:
- std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
- renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- renderer->insertReorderBarrier(true);
+static const char* SHORT_OPTIONS = "c:r:h";
- 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));
- renderer->drawRenderNode(card.get());
- cards.push_back(card);
- }
- }
+void parseOptions(int argc, char* argv[]) {
+ int c;
+ // temporary variable
+ int count;
+ bool error = false;
+ opterr = 0;
- renderer->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);
+ while (true) {
- DisplayListCanvas* renderer = startRecording(node.get());
- renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
- endRecording(renderer, node.get());
- return node;
- }
-};
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
-class RectGridAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
- renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- renderer->insertReorderBarrier(true);
+ c = getopt_long(argc, argv, SHORT_OPTIONS, LONG_OPTIONS, &option_index);
- card = createCard(40, 40, 200, 200);
- renderer->drawRenderNode(card.get());
+ if (c == -1)
+ break;
- renderer->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);
- }
-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->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ switch (c) {
+ case 0:
+ // Option set a flag, don't need to do anything
+ // (although none of the current LONG_OPTIONS do this...)
+ break;
- DisplayListCanvas* renderer = startRecording(node.get());
- renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
+ case 'l':
+ listTests();
+ exit(EXIT_SUCCESS);
+ break;
- float rects[width * height];
- int index = 0;
- for (int xOffset = 0; xOffset < width; xOffset+=2) {
- for (int yOffset = 0; yOffset < height; yOffset+=2) {
- rects[index++] = xOffset;
- rects[index++] = yOffset;
- rects[index++] = xOffset + 1;
- rects[index++] = yOffset + 1;
+ case 'c':
+ count = atoi(optarg);
+ if (!count) {
+ fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
+ error = true;
+ } else {
+ gFrameCount = (count > 0 ? count : INT_MAX);
+ }
+ break;
+
+ case 'r':
+ count = atoi(optarg);
+ if (!count) {
+ fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
+ error = true;
+ } else {
+ gRepeatCount = (count > 0 ? count : INT_MAX);
}
+ break;
+
+ case 'h':
+ printHelp();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case '?':
+ fprintf(stderr, "Unrecognized option '%s'\n", argv[optind - 1]);
+ // fall-through
+ default:
+ error = true;
+ break;
}
- int count = width * height;
-
- SkPaint paint;
- paint.setColor(0xff00ffff);
- renderer->drawRects(rects, count, &paint);
-
- endRecording(renderer, node.get());
- return node;
- }
-};
-
-class OvalAnimation : public TreeContentAnimation {
-public:
- sp<RenderNode> card;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
- renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
- renderer->insertReorderBarrier(true);
-
- card = createCard(40, 40, 400, 400);
- renderer->drawRenderNode(card.get());
-
- renderer->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);
}
-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->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
-
- DisplayListCanvas* renderer = startRecording(node.get());
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(0xFF000000);
- renderer->drawOval(0, 0, width, height, paint);
-
- endRecording(renderer, node.get());
- return node;
+ if (error) {
+ fprintf(stderr, "Try 'hwuitest --help' for more information.\n");
+ exit(EXIT_FAILURE);
}
-};
-struct cstr_cmp {
- bool operator()(const char *a, const char *b) const {
- return std::strcmp(a, b) < 0;
+ /* Print any remaining command line arguments (not options). */
+ if (optind < argc) {
+ do {
+ const char* test = argv[optind++];
+ auto pos = testMap().find(test);
+ if (pos == testMap().end()) {
+ fprintf(stderr, "Unknown test '%s'\n", test);
+ exit(EXIT_FAILURE);
+ } else {
+ gRunTests.push_back(pos->second);
+ }
+ } while (optind < argc);
+ } else {
+ gRunTests.push_back(testMap()["shadowgrid"]);
}
-};
-
-typedef void (*testProc)(int);
-
-std::map<const char*, testProc, cstr_cmp> gTestMap {
- {"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
- {"shadowgrid2", TreeContentAnimation::run<ShadowGrid2Animation>},
- {"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
- {"oval", TreeContentAnimation::run<OvalAnimation> },
-};
+}
int main(int argc, char* argv[]) {
- const char* testName = argc > 1 ? argv[1] : "shadowgrid";
- testProc proc = gTestMap[testName];
- if(!proc) {
- printf("Error: couldn't find test %s\n", testName);
- return 1;
- }
- int loopCount = 1;
- if (argc > 2) {
- loopCount = atoi(argv[2]);
- if (!loopCount) {
- printf("Invalid loop count!\n");
- return 1;
- }
- }
- int frameCount = 150;
- if (argc > 3) {
- frameCount = atoi(argv[3]);
- if (frameCount < 1) {
- printf("Invalid frame count!\n");
- return 1;
+ parseOptions(argc, argv);
+
+ BenchmarkOptions opts;
+ opts.count = gFrameCount;
+ for (int i = 0; i < gRepeatCount; i++) {
+ for (auto&& test : gRunTests) {
+ test.functor(opts);
}
}
- if (loopCount < 0) {
- loopCount = INT_MAX;
- }
- for (int i = 0; i < loopCount; i++) {
- proc(frameCount);
- }
printf("Success!\n");
return 0;
}