Add initial OpReorderer benchmarks
Change-Id: I6ca8ea89be2159331b2ad7031769c65f54161918
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 1a43658..842f575 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -263,4 +263,9 @@
microbench/DisplayListCanvasBench.cpp \
microbench/LinearAllocatorBench.cpp
+ifeq (true, $(HWUI_NEW_OPS))
+ LOCAL_SRC_FILES += \
+ microbench/OpReordererBench.cpp
+endif
+
include $(BUILD_EXECUTABLE)
diff --git a/libs/hwui/microbench/OpReordererBench.cpp b/libs/hwui/microbench/OpReordererBench.cpp
new file mode 100644
index 0000000..4c8dedf
--- /dev/null
+++ b/libs/hwui/microbench/OpReordererBench.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 <benchmark/Benchmark.h>
+
+#include "BakedOpState.h"
+#include "BakedOpRenderer.h"
+#include "OpReorderer.h"
+#include "RecordedOp.h"
+#include "RecordingCanvas.h"
+#include "unit_tests/TestUtils.h"
+#include "microbench/MicroBench.h"
+
+#include <vector>
+
+using namespace android;
+using namespace android::uirenderer;
+
+auto sReorderingDisplayList = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);
+ SkPaint paint;
+
+ // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
+ // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ for (int i = 0; i < 30; i++) {
+ canvas.translate(0, 10);
+ canvas.drawRect(0, 0, 10, 10, paint);
+ canvas.drawBitmap(bitmap, 5, 0, nullptr);
+ }
+ canvas.restore();
+});
+
+BENCHMARK_NO_ARG(BM_OpReorderer_defer);
+void BM_OpReorderer_defer::Run(int iters) {
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ OpReorderer reorderer;
+ reorderer.defer(200, 200, *sReorderingDisplayList);
+ MicroBench::DoNotOptimize(&reorderer);
+ }
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_NO_ARG(BM_OpReorderer_deferAndRender);
+void BM_OpReorderer_deferAndRender::Run(int iters) {
+ TestUtils::runOnRenderThread([this, iters](RenderState& renderState, Caches& caches) {
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ OpReorderer reorderer;
+ reorderer.defer(200, 200, *sReorderingDisplayList);
+ MicroBench::DoNotOptimize(&reorderer);
+
+ BakedOpRenderer::Info info(caches, renderState, 200, 200, true);
+ reorderer.replayBakedOps<BakedOpRenderer>(&info);
+ }
+ StopBenchmarkTiming();
+ });
+}
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 26aae90..15ccd6a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -574,12 +574,7 @@
RenderThread& thread = RenderThread::getInstance();
void* retval;
task->setReturnPtr(&retval);
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
- AutoMutex _lock(mutex);
- thread.queue(&syncTask);
- condition.wait(mutex);
+ thread.queueAndWait(task);
return retval;
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 64075f1..8fcd109 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -312,6 +312,16 @@
}
}
+void RenderThread::queueAndWait(RenderTask* task) {
+ Mutex mutex;
+ Condition condition;
+ SignalingRenderTask syncTask(task, &mutex, &condition);
+
+ AutoMutex _lock(mutex);
+ queue(&syncTask);
+ condition.wait(mutex);
+}
+
void RenderThread::queueAtFront(RenderTask* task) {
AutoMutex _lock(mLock);
mQueue.queueAtFront(task);
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 8096099..f3444a8 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -39,6 +39,7 @@
namespace uirenderer {
class RenderState;
+class TestUtils;
namespace renderthread {
@@ -76,6 +77,7 @@
// RenderThread takes complete ownership of tasks that are queued
// and will delete them after they are run
ANDROID_API void queue(RenderTask* task);
+ ANDROID_API void queueAndWait(RenderTask* task);
ANDROID_API void queueAtFront(RenderTask* task);
void queueAt(RenderTask* task, nsecs_t runAtNs);
void remove(RenderTask* task);
@@ -101,6 +103,7 @@
friend class Singleton<RenderThread>;
friend class DispatchFrameCallbacks;
friend class RenderProxy;
+ friend class android::uirenderer::TestUtils;
RenderThread();
virtual ~RenderThread();
diff --git a/libs/hwui/unit_tests/TestUtils.h b/libs/hwui/unit_tests/TestUtils.h
index bb58928..80d83a2 100644
--- a/libs/hwui/unit_tests/TestUtils.h
+++ b/libs/hwui/unit_tests/TestUtils.h
@@ -17,8 +17,11 @@
#define TEST_UTILS_H
#include <Matrix.h>
-#include <Snapshot.h>
+#include <Rect.h>
#include <RenderNode.h>
+#include <renderstate/RenderState.h>
+#include <renderthread/RenderThread.h>
+#include <Snapshot.h>
#include <memory>
@@ -48,7 +51,9 @@
static SkBitmap createSkBitmap(int width, int height) {
SkBitmap bitmap;
- bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+ SkImageInfo info = SkImageInfo::MakeUnknown(width, height);
+ bitmap.setInfo(info);
+ bitmap.allocPixels(info);
return bitmap;
}
@@ -78,6 +83,32 @@
node->syncProperties();
node->syncDisplayList();
}
+
+ typedef std::function<void(RenderState& state, Caches& caches)> RtCallback;
+
+ class TestTask : public renderthread::RenderTask {
+ public:
+ TestTask(RtCallback rtCallback)
+ : rtCallback(rtCallback) {}
+ virtual ~TestTask() {}
+ virtual void run() override {
+ // RenderState only valid once RenderThread is running, so queried here
+ RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
+
+ renderState.onGLContextCreated();
+ rtCallback(renderState, Caches::getInstance());
+ renderState.onGLContextDestroyed();
+ };
+ RtCallback rtCallback;
+ };
+
+ /**
+ * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely.
+ */
+ static void runOnRenderThread(RtCallback rtCallback) {
+ TestTask task(rtCallback);
+ renderthread::RenderThread::getInstance().queueAndWait(&task);
+ }
}; // class TestUtils
} /* namespace uirenderer */