aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/Benchmark.h1
-rw-r--r--bench/nanobench.cpp232
-rw-r--r--bench/nanobench.h79
-rw-r--r--bench/nanobenchAndroid.cpp160
-rw-r--r--bench/nanobenchAndroid.h49
-rw-r--r--gyp/bench.gyp14
6 files changed, 438 insertions, 97 deletions
diff --git a/bench/Benchmark.h b/bench/Benchmark.h
index c30167e572..5ba6e91108 100644
--- a/bench/Benchmark.h
+++ b/bench/Benchmark.h
@@ -57,6 +57,7 @@ public:
kRaster_Backend,
kGPU_Backend,
kPDF_Backend,
+ kHWUI_Backend,
};
// Call to determine whether the benchmark is intended for
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 5e059328ad..4bc1484da0 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -7,6 +7,8 @@
#include <ctype.h>
+#include "nanobench.h"
+
#include "Benchmark.h"
#include "CrashHandler.h"
#include "DecodingBench.h"
@@ -32,6 +34,10 @@
#include "SkSurface.h"
#include "SkTaskGroup.h"
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ #include "nanobenchAndroid.h"
+#endif
+
#if SK_SUPPORT_GPU
#include "gl/GrGLDefines.h"
#include "GrContextFactory.h"
@@ -86,24 +92,100 @@ static SkString humanize(double ms) {
}
#define HUMANIZE(ms) humanize(ms).c_str()
-static double time(int loops, Benchmark* bench, SkCanvas* canvas, SkGLContext* gl) {
+bool Target::init(SkImageInfo info, Benchmark* bench) {
+ if (Benchmark::kRaster_Backend == config.backend) {
+ this->surface.reset(SkSurface::NewRaster(info));
+ if (!this->surface.get()) {
+ return false;
+ }
+ }
+ return true;
+}
+bool Target::capturePixels(SkBitmap* bmp) {
+ if (!this->surface.get()) {
+ return false;
+ }
+ SkCanvas* canvas = this->surface->getCanvas();
+ if (!canvas) {
+ return false;
+ }
+ bmp->setInfo(canvas->imageInfo());
+ if (!canvas->readPixels(bmp, 0, 0)) {
+ SkDebugf("Can't read canvas pixels.\n");
+ return false;
+ }
+ return true;
+}
+
+#if SK_SUPPORT_GPU
+struct GPUTarget : public Target {
+ explicit GPUTarget(const Config& c) : Target(c), gl(NULL) { }
+ SkGLContext* gl;
+
+ void setup() override {
+ this->gl->makeCurrent();
+ // Make sure we're done with whatever came before.
+ SK_GL(*this->gl, Finish());
+ }
+ void endTiming() override {
+ if (this->gl) {
+ SK_GL(*this->gl, Flush());
+ this->gl->swapBuffers();
+ }
+ }
+ void fence() override {
+ SK_GL(*this->gl, Finish());
+ }
+
+ bool needsFrameTiming() const override { return true; }
+ bool init(SkImageInfo info, Benchmark* bench) override {
+ uint32_t flags = this->config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
+ SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+ this->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(this->config.ctxType),
+ SkSurface::kNo_Budgeted, info,
+ this->config.samples, &props));
+ this->gl = gGrFactory->getGLContext(this->config.ctxType);
+ if (!this->surface.get()) {
+ return false;
+ }
+ return true;
+ }
+ void fillOptions(ResultsWriter* log) override {
+ const GrGLubyte* version;
+ SK_GL_RET(*this->gl, version, GetString(GR_GL_VERSION));
+ log->configOption("GL_VERSION", (const char*)(version));
+
+ SK_GL_RET(*this->gl, version, GetString(GR_GL_RENDERER));
+ log->configOption("GL_RENDERER", (const char*) version);
+
+ SK_GL_RET(*this->gl, version, GetString(GR_GL_VENDOR));
+ log->configOption("GL_VENDOR", (const char*) version);
+
+ SK_GL_RET(*this->gl, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
+ log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
+ }
+};
+
+#endif
+
+static double time(int loops, Benchmark* bench, SkCanvas* canvas, Target* target) {
if (canvas) {
canvas->clear(SK_ColorWHITE);
}
WallTimer timer;
timer.start();
+ if (target) {
+ canvas = target->beginTiming(canvas);
+ }
if (bench) {
bench->draw(loops, canvas);
}
if (canvas) {
canvas->flush();
}
-#if SK_SUPPORT_GPU
- if (gl) {
- SK_GL(*gl, Flush());
- gl->swapBuffers();
+ if (target) {
+ target->endTiming();
}
-#endif
timer.end();
return timer.fWall;
}
@@ -137,19 +219,22 @@ static int clamp_loops(int loops) {
return loops;
}
-static bool write_canvas_png(SkCanvas* canvas, const SkString& filename) {
+static bool write_canvas_png(Target* target, const SkString& filename) {
+
if (filename.isEmpty()) {
return false;
}
- if (kUnknown_SkColorType == canvas->imageInfo().colorType()) {
+ if (target->surface.get() && target->surface->getCanvas() &&
+ kUnknown_SkColorType == target->surface->getCanvas()->imageInfo().colorType()) {
return false;
}
+
SkBitmap bmp;
- bmp.setInfo(canvas->imageInfo());
- if (!canvas->readPixels(&bmp, 0, 0)) {
- SkDebugf("Can't read canvas pixels.\n");
+
+ if (!target->capturePixels(&bmp)) {
return false;
}
+
SkString dir = SkOSPath::Dirname(filename.c_str());
if (!sk_mkdir(dir.c_str())) {
SkDebugf("Can't make dir %s.\n", dir.c_str());
@@ -215,14 +300,7 @@ static int cpu_bench(const double overhead, Benchmark* bench, SkCanvas* canvas,
return loops;
}
-#if SK_SUPPORT_GPU
-static void setup_gl(SkGLContext* gl) {
- gl->makeCurrent();
- // Make sure we're done with whatever came before.
- SK_GL(*gl, Finish());
-}
-
-static int gpu_bench(SkGLContext* gl,
+static int gpu_bench(Target* target,
Benchmark* bench,
SkCanvas* canvas,
double* samples) {
@@ -242,7 +320,7 @@ static int gpu_bench(SkGLContext* gl,
// _this_ round, not still timing last round. We force this by looping
// more times than any reasonable GPU will allow frames to lag.
for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
- elapsed = time(loops, bench, canvas, gl);
+ elapsed = time(loops, bench, canvas, target);
}
} while (elapsed < FLAGS_gpuMs);
@@ -250,8 +328,8 @@ static int gpu_bench(SkGLContext* gl,
loops = (int)ceil(loops * FLAGS_gpuMs / elapsed);
loops = clamp_loops(loops);
- // Might as well make sure we're not still timing our calibration.
- SK_GL(*gl, Finish());
+ // Make sure we're not still timing our calibration.
+ target->fence();
} else {
loops = detect_forever_loops(loops);
}
@@ -259,16 +337,16 @@ static int gpu_bench(SkGLContext* gl,
// Pretty much the same deal as the calibration: do some warmup to make
// sure we're timing steady-state pipelined frames.
for (int i = 0; i < FLAGS_gpuFrameLag; i++) {
- time(loops, bench, canvas, gl);
+ time(loops, bench, canvas, target);
}
// Now, actually do the timing!
for (int i = 0; i < FLAGS_samples; i++) {
- samples[i] = time(loops, bench, canvas, gl) / loops;
+ samples[i] = time(loops, bench, canvas, target) / loops;
}
+
return loops;
}
-#endif
static SkString to_lower(const char* str) {
SkString lower(str);
@@ -278,30 +356,6 @@ static SkString to_lower(const char* str) {
return lower;
}
-struct Config {
- const char* name;
- Benchmark::Backend backend;
- SkColorType color;
- SkAlphaType alpha;
- int samples;
-#if SK_SUPPORT_GPU
- GrContextFactory::GLContextType ctxType;
- bool useDFText;
-#else
- int bogusInt;
- bool bogusBool;
-#endif
-};
-
-struct Target {
- explicit Target(const Config& c) : config(c) {}
- const Config config;
- SkAutoTDelete<SkSurface> surface;
-#if SK_SUPPORT_GPU
- SkGLContext* gl;
-#endif
-};
-
static bool is_cpu_config_allowed(const char* name) {
for (int i = 0; i < FLAGS_config.count(); i++) {
if (to_lower(FLAGS_config[i]).equals(name)) {
@@ -373,6 +427,14 @@ static void create_configs(SkTDArray<Config>* configs) {
#endif
}
#endif
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ if (is_cpu_config_allowed("hwui")) {
+ Config config = { "hwui", Benchmark::kHWUI_Backend, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType, 0, kBogusGLContextType, false };
+ configs->push(config);
+ }
+#endif
}
// If bench is enabled for config, returns a Target* for it, otherwise NULL.
@@ -384,23 +446,25 @@ static Target* is_enabled(Benchmark* bench, const Config& config) {
SkImageInfo info = SkImageInfo::Make(bench->getSize().fX, bench->getSize().fY,
config.color, config.alpha);
- Target* target = new Target(config);
+ Target* target = NULL;
- if (Benchmark::kRaster_Backend == config.backend) {
- target->surface.reset(SkSurface::NewRaster(info));
- }
+ switch (config.backend) {
#if SK_SUPPORT_GPU
- else if (Benchmark::kGPU_Backend == config.backend) {
- uint32_t flags = config.useDFText ? SkSurfaceProps::kUseDistanceFieldFonts_Flag : 0;
- SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
- target->surface.reset(SkSurface::NewRenderTarget(gGrFactory->get(config.ctxType),
- SkSurface::kNo_Budgeted, info,
- config.samples, &props));
- target->gl = gGrFactory->getGLContext(config.ctxType);
- }
+ case Benchmark::kGPU_Backend:
+ target = new GPUTarget(config);
+ break;
+#endif
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ case Benchmark::kHWUI_Backend:
+ target = new HWUITarget(config, bench);
+ break;
#endif
+ default:
+ target = new Target(config);
+ break;
+ }
- if (Benchmark::kNonRendering_Backend != config.backend && !target->surface.get()) {
+ if (!target->init(info, bench)) {
delete target;
return NULL;
}
@@ -418,22 +482,6 @@ static void create_targets(SkTDArray<Target*>* targets, Benchmark* b,
}
}
-#if SK_SUPPORT_GPU
-static void fill_gpu_options(ResultsWriter* log, SkGLContext* ctx) {
- const GrGLubyte* version;
- SK_GL_RET(*ctx, version, GetString(GR_GL_VERSION));
- log->configOption("GL_VERSION", (const char*)(version));
-
- SK_GL_RET(*ctx, version, GetString(GR_GL_RENDERER));
- log->configOption("GL_RENDERER", (const char*) version);
-
- SK_GL_RET(*ctx, version, GetString(GR_GL_VENDOR));
- log->configOption("GL_VENDOR", (const char*) version);
-
- SK_GL_RET(*ctx, version, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
- log->configOption("GL_SHADING_LANGUAGE_VERSION", (const char*) version);
-}
-#endif
class BenchmarkStream {
public:
@@ -790,32 +838,26 @@ int nanobench_main() {
bench->preDraw();
}
for (int j = 0; j < targets.count(); j++) {
+ // During HWUI output this canvas may be NULL.
SkCanvas* canvas = targets[j]->surface.get() ? targets[j]->surface->getCanvas() : NULL;
const char* config = targets[j]->config.name;
-#if SK_SUPPORT_GPU
- if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
- setup_gl(targets[j]->gl);
- }
-#endif
-
+ targets[j]->setup();
bench->perCanvasPreDraw(canvas);
const int loops =
-#if SK_SUPPORT_GPU
- Benchmark::kGPU_Backend == targets[j]->config.backend
- ? gpu_bench(targets[j]->gl, bench.get(), canvas, samples.get())
- :
-#endif
- cpu_bench( overhead, bench.get(), canvas, samples.get());
+ targets[j]->needsFrameTiming()
+ ? gpu_bench(targets[j], bench.get(), canvas, samples.get())
+ : cpu_bench(overhead, bench.get(), canvas, samples.get());
bench->perCanvasPostDraw(canvas);
- if (canvas && !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
+ if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &&
+ !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) {
SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config);
pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniqueName());
pngFilename.append(".png");
- write_canvas_png(canvas, pngFilename);
+ write_canvas_png(targets[j], pngFilename);
}
if (kFailedLoops == loops) {
@@ -827,11 +869,7 @@ int nanobench_main() {
log->config(config);
log->configOption("name", bench->getName());
benchStream.fillCurrentOptions(log.get());
-#if SK_SUPPORT_GPU
- if (Benchmark::kGPU_Backend == targets[j]->config.backend) {
- fill_gpu_options(log.get(), targets[j]->gl);
- }
-#endif
+ targets[j]->fillOptions(log.get());
log->metric("min_ms", stats.min);
if (runs++ % FLAGS_flushEvery == 0) {
log->flush();
diff --git a/bench/nanobench.h b/bench/nanobench.h
new file mode 100644
index 0000000000..a38b5f5772
--- /dev/null
+++ b/bench/nanobench.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef nanobench_DEFINED
+#define nanobench_DEFINED
+
+#include "Benchmark.h"
+#include "SkImageInfo.h"
+#include "SkSurface.h"
+#include "SkTypes.h"
+
+#if SK_SUPPORT_GPU
+#include "GrContextFactory.h"
+#endif
+
+class ResultsWriter;
+class SkBitmap;
+class SkCanvas;
+
+struct Config {
+ const char* name;
+ Benchmark::Backend backend;
+ SkColorType color;
+ SkAlphaType alpha;
+ int samples;
+#if SK_SUPPORT_GPU
+ GrContextFactory::GLContextType ctxType;
+ bool useDFText;
+#else
+ int bogusInt;
+ bool bogusBool;
+#endif
+};
+
+struct Target {
+ explicit Target(const Config& c) : config(c) { }
+ virtual ~Target() { }
+
+ const Config config;
+ SkAutoTDelete<SkSurface> surface;
+
+ /** Called once per target, immediately before any timing or drawing. */
+ virtual void setup() { }
+
+ /** Called *after* the clock timer is started, before the benchmark
+ is drawn. */
+ virtual SkCanvas* beginTiming(SkCanvas* canvas) { return canvas; }
+
+ /** Called *after* a benchmark is drawn, but before the clock timer
+ is stopped. */
+ virtual void endTiming() { }
+
+ /** Called between benchmarks (or between calibration and measured
+ runs) to make sure all pending work in drivers / threads is
+ complete. */
+ virtual void fence() { }
+
+ /** CPU-like targets can just be timed, but GPU-like
+ targets need to pay attention to frame boundaries
+ or other similar details. */
+ virtual bool needsFrameTiming() const { return false; }
+
+ /** Called once per target, during program initialization.
+ Returns false if initialization fails. */
+ virtual bool init(SkImageInfo info, Benchmark* bench);
+
+ /** Stores any pixels drawn to the screen in the bitmap.
+ Returns false on error. */
+ virtual bool capturePixels(SkBitmap* bmp);
+
+ /** Writes any config-specific data to the log. */
+ virtual void fillOptions(ResultsWriter*) { }
+};
+
+#endif // nanobench_DEFINED
diff --git a/bench/nanobenchAndroid.cpp b/bench/nanobenchAndroid.cpp
new file mode 100644
index 0000000000..8bda1c8625
--- /dev/null
+++ b/bench/nanobenchAndroid.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "nanobenchAndroid.h"
+
+#include "AnimationContext.h"
+#include "IContextFactory.h"
+#include "SkiaCanvasProxy.h"
+#include "android/rect.h"
+#include "android/native_window.h"
+#include "renderthread/TimeLord.h"
+
+namespace {
+
+/**
+ * Helper class for setting up android::uirenderer::renderthread::RenderProxy.
+ */
+class ContextFactory : public android::uirenderer::IContextFactory {
+public:
+ android::uirenderer::AnimationContext* createAnimationContext
+ (android::uirenderer::renderthread::TimeLord& clock) override {
+ return new android::uirenderer::AnimationContext(clock);
+ }
+};
+
+}
+
+HWUITarget::HWUITarget(const Config& c, Benchmark* bench) : Target(c) { }
+
+void HWUITarget::setup() {
+ this->proxy->fence();
+}
+
+SkCanvas* HWUITarget::beginTiming(SkCanvas* canvas) {
+ this->renderer->prepare();
+ this->renderer->clipRect(0, 0, this->size.width(), this->size.height(),
+ SkRegion::Op::kReplace_Op);
+ SkCanvas* targetCanvas = this->renderer->asSkCanvas();
+ if (targetCanvas) {
+ this->fc.reset(targetCanvas);
+ canvas = &this->fc;
+ // This might minimally distort timing, but canvas isn't valid outside the timer.
+ canvas->clear(SK_ColorWHITE);
+ }
+ return canvas;
+}
+
+void HWUITarget::endTiming() {
+ this->renderer->finish();
+ this->rootNode->setStagingDisplayList(this->renderer->finishRecording());
+ this->proxy->syncAndDrawFrame();
+ // Surprisingly, calling this->proxy->fence() here appears to make no difference to
+ // the timings we record.
+}
+
+void HWUITarget::fence() {
+ this->proxy->fence();
+}
+
+bool HWUITarget::needsFrameTiming() const {
+ return true;
+}
+
+bool HWUITarget::init(SkImageInfo info, Benchmark* bench) {
+ // extracted from DMSrcSinkAndroid.cpp's HWUISink::draw()
+ size.set(bench->getSize().x(), bench->getSize().y());
+ android::BufferQueue::createBufferQueue(&this->producer, &this->consumer);
+ this->cpuConsumer = new android::CpuConsumer(this->consumer, 1);
+ this->cpuConsumer->setName(android::String8("SkiaBenchmarkClient"));
+ this->cpuConsumer->setDefaultBufferSize(size.width(), size.height());
+ this->androidSurface = new android::Surface(this->producer);
+ native_window_set_buffers_dimensions(this->androidSurface.get(),
+ size.width(), size.height());
+ native_window_set_buffers_format(this->androidSurface.get(),
+ android::PIXEL_FORMAT_RGBA_8888);
+ native_window_set_usage(this->androidSurface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_NEVER |
+ GRALLOC_USAGE_HW_RENDER);
+ this->rootNode.reset(new android::uirenderer::RenderNode());
+ this->rootNode->incStrong(nullptr);
+ this->rootNode->mutateStagingProperties().setLeftTopRightBottom
+ (0, 0, size.width(), size.height());
+ this->rootNode->mutateStagingProperties().setClipToBounds(false);
+ this->rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
+ ContextFactory factory;
+ this->proxy.reset
+ (new android::uirenderer::renderthread::RenderProxy(false, this->rootNode, &factory));
+ this->proxy->loadSystemProperties();
+ this->proxy->initialize(this->androidSurface.get());
+ float lightX = size.width() / 2.0f;
+ android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
+ this->proxy->setup(size.width(), size.height(), lightVector, 800.0f,
+ 255 * 0.075f, 255 * 0.15f);
+ this->renderer.reset(new android::uirenderer::DisplayListRenderer());
+ this->renderer->setViewport(size.width(), size.height());
+
+ // Since we have no SkSurface for HWUI, other parts of the code base have to
+ // explicitly work around the fact that it may be invalid / have no SkCanvas.
+
+ return true;
+}
+
+bool HWUITarget::capturePixels(SkBitmap* bmp) {
+ SkImageInfo destinationConfig =
+ SkImageInfo::Make(this->size.width(), this->size.height(),
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ bmp->allocPixels(destinationConfig);
+ sk_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
+ this->size.width() * this->size.height());
+
+ android::CpuConsumer::LockedBuffer nativeBuffer;
+ android::status_t retval = this->cpuConsumer->lockNextBuffer(&nativeBuffer);
+ if (retval == android::BAD_VALUE) {
+ SkDebugf("write_canvas_png() got no buffer; returning transparent");
+ // No buffer ready to read - commonly triggered by dm sending us
+ // a no-op source, or calling code that doesn't do anything on this
+ // backend.
+ bmp->eraseColor(SK_ColorTRANSPARENT);
+ return false;
+ } else if (retval) {
+ SkDebugf("Failed to lock buffer to read pixels: %d.", retval);
+ return false;
+ }
+
+ // Move the pixels into the destination SkBitmap
+
+ SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 &&
+ "Native buffer not RGBA!");
+ SkImageInfo nativeConfig =
+ SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+
+ // Android stride is in pixels, Skia stride is in bytes
+ SkBitmap nativeWrapper;
+ bool success =
+ nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
+ if (!success) {
+ SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
+ return false;
+ }
+
+ SK_ALWAYSBREAK(bmp->colorType() == kRGBA_8888_SkColorType &&
+ "Destination buffer not RGBA!");
+ success =
+ nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0, 0);
+ if (!success) {
+ SkDebugf("Failed to extract pixels from HWUI buffer");
+ return false;
+ }
+
+ this->cpuConsumer->unlockBuffer(nativeBuffer);
+
+ return true;
+}
+
+
diff --git a/bench/nanobenchAndroid.h b/bench/nanobenchAndroid.h
new file mode 100644
index 0000000000..3baeb1270f
--- /dev/null
+++ b/bench/nanobenchAndroid.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef nanobenchAndroid_DEFINED
+#define nanobenchAndroid_DEFINED
+
+#include "DisplayListRenderer.h"
+#include "RenderNode.h"
+#include "SkAndroidSDKCanvas.h"
+#include "gui/BufferQueue.h"
+#include "gui/CpuConsumer.h"
+#include "gui/IGraphicBufferConsumer.h"
+#include "gui/IGraphicBufferProducer.h"
+#include "gui/Surface.h"
+#include "renderthread/RenderProxy.h"
+
+#include "nanobench.h"
+
+struct HWUITarget : public Target {
+ explicit HWUITarget(const Config& c, Benchmark* bench);
+
+ SkAutoTDelete<android::uirenderer::RenderNode> rootNode;
+ SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy;
+ SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer;
+ android::sp<android::IGraphicBufferProducer> producer;
+ android::sp<android::IGraphicBufferConsumer> consumer;
+ android::sp<android::CpuConsumer> cpuConsumer;
+ android::sp<android::Surface> androidSurface;
+ SkISize size;
+ SkAndroidSDKCanvas fc;
+
+ void setup() override;
+ SkCanvas* beginTiming(SkCanvas* canvas) override;
+ void endTiming() override;
+ void fence() override;
+ bool needsFrameTiming() const override;
+
+ /// Returns false if initialization fails
+ bool init(SkImageInfo info, Benchmark* bench) override;
+ bool capturePixels(SkBitmap* bmp) override;
+};
+
+
+
+#endif // nanobenchAndroid_DEFINED
diff --git a/gyp/bench.gyp b/gyp/bench.gyp
index b4442918a6..1370b5383a 100644
--- a/gyp/bench.gyp
+++ b/gyp/bench.gyp
@@ -37,6 +37,20 @@
['skia_android_framework', {
'libraries': [
'-lskia',
+ '-landroid',
+ '-lgui',
+ '-lhwui',
+ '-lutils',
+ ],
+ 'include_dirs': [
+ '../../../frameworks/base/libs/hwui/',
+ '../../../frameworks/native/include/',
+ ],
+ 'sources': [
+ '../bench/nanobenchAndroid.cpp',
+ ],
+ 'dependencies': [
+ 'utils.gyp:android_utils',
],
}],
],