diff options
-rw-r--r-- | bench/nanobenchAndroid.cpp | 120 | ||||
-rw-r--r-- | bench/nanobenchAndroid.h | 21 | ||||
-rw-r--r-- | dm/DMSrcSinkAndroid.cpp | 152 | ||||
-rw-r--r-- | gyp/utils.gyp | 2 | ||||
-rw-r--r-- | src/utils/android/SkHwuiRenderer.cpp | 130 | ||||
-rw-r--r-- | src/utils/android/SkHwuiRenderer.h | 42 |
6 files changed, 193 insertions, 274 deletions
diff --git a/bench/nanobenchAndroid.cpp b/bench/nanobenchAndroid.cpp index 8bda1c8625..3d5cda4929 100644 --- a/bench/nanobenchAndroid.cpp +++ b/bench/nanobenchAndroid.cpp @@ -14,51 +14,32 @@ #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); - } -}; - -} +/* These functions are only compiled in the Android Framework. */ HWUITarget::HWUITarget(const Config& c, Benchmark* bench) : Target(c) { } void HWUITarget::setup() { - this->proxy->fence(); + this->renderer.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(); + SkCanvas* targetCanvas = this->renderer.prepareToDraw(); 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. + this->renderer.finishDrawing(); } void HWUITarget::fence() { - this->proxy->fence(); + this->renderer.proxy->fence(); } bool HWUITarget::needsFrameTiming() const { @@ -66,95 +47,12 @@ bool HWUITarget::needsFrameTiming() const { } 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. - + this->renderer.initialize({bench->getSize().x(), bench->getSize().y()}); 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; + return this->renderer.capturePixels(bmp); } diff --git a/bench/nanobenchAndroid.h b/bench/nanobenchAndroid.h index 3baeb1270f..7f6ff441d6 100644 --- a/bench/nanobenchAndroid.h +++ b/bench/nanobenchAndroid.h @@ -8,29 +8,15 @@ #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 "SkHwuiRenderer.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; + SkHwuiRenderer renderer; SkAndroidSDKCanvas fc; void setup() override; @@ -39,11 +25,8 @@ struct HWUITarget : public Target { 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/dm/DMSrcSinkAndroid.cpp b/dm/DMSrcSinkAndroid.cpp index 29cf055b4d..63c9d82848 100644 --- a/dm/DMSrcSinkAndroid.cpp +++ b/dm/DMSrcSinkAndroid.cpp @@ -8,163 +8,27 @@ #include "DMSrcSink.h" #include "DMSrcSinkAndroid.h" -#include "AnimationContext.h" -#include "DisplayListRenderer.h" -#include "IContextFactory.h" -#include "RenderNode.h" #include "SkAndroidSDKCanvas.h" #include "SkCanvas.h" +#include "SkHwuiRenderer.h" #include "SkiaCanvasProxy.h" -#include "SkTLazy.h" -#include "SkMaskFilter.h" -#include "SkPictureRecorder.h" #include "SkStream.h" -#include "android/rect.h" -#include "android/native_window.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 "renderthread/TimeLord.h" /* These functions are only compiled in the Android Framework. */ -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); - } -}; - -} // namespace - namespace DM { Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const { - // Do all setup in this function because we don't know the size - // for the RenderNode and RenderProxy during the constructor. - // In practice this doesn't seem too expensive. - const SkISize size = src.size(); - - // Based on android::SurfaceTexture_init() - android::sp<android::IGraphicBufferProducer> producer; - android::sp<android::IGraphicBufferConsumer> consumer; - android::BufferQueue::createBufferQueue(&producer, &consumer); - - // Consumer setup - - android::sp<android::CpuConsumer> cpuConsumer = - new android::CpuConsumer(consumer, 1); - cpuConsumer->setName(android::String8("SkiaTestClient")); - cpuConsumer->setDefaultBufferSize(size.width(), size.height()); - - // Producer setup - - android::sp<android::Surface> surface = new android::Surface(producer); - native_window_set_buffers_dimensions(surface.get(), size.width(), size.height()); - native_window_set_buffers_format(surface.get(), android::PIXEL_FORMAT_RGBA_8888); - native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_NEVER | - GRALLOC_USAGE_HW_RENDER); - - // RenderNode setup based on hwui/tests/main.cpp:TreeContentAnimation - SkAutoTDelete<android::uirenderer::RenderNode> rootNode - (new android::uirenderer::RenderNode()); - rootNode->incStrong(nullptr); - - // Values set here won't be applied until the framework has called - // RenderNode::pushStagingPropertiesChanges() during RenderProxy::syncAndDrawFrame(). - rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, size.width(), size.height()); - rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::X | - android::uirenderer::RenderNode::Y); - rootNode->mutateStagingProperties().setClipToBounds(false); - rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC); - - // RenderProxy setup based on hwui/tests/main.cpp:TreeContentAnimation - ContextFactory factory; - SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy - (new android::uirenderer::renderthread::RenderProxy(false, rootNode, &factory)); - proxy->loadSystemProperties(); - - proxy->initialize(surface.get()); - - float lightX = size.width() / 2.0f; - android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f }; - proxy->setup(size.width(), size.height(), lightVector, 800.0f, 255 * 0.075f, 255 * 0.15f); - - // Do the draw - - SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer - (new android::uirenderer::DisplayListRenderer()); - renderer->setViewport(size.width(), size.height()); - renderer->prepare(); - renderer->clipRect(0, 0, size.width(), size.height(), SkRegion::Op::kReplace_Op); - - Error err = src.draw(renderer->asSkCanvas()); + SkHwuiRenderer renderer; + renderer.initialize(src.size()); + SkCanvas* canvas = renderer.prepareToDraw(); + Error err = src.draw(canvas); if (!err.isEmpty()) { return err; } - - renderer->finish(); - rootNode->setStagingDisplayList(renderer->finishRecording()); - - proxy->syncAndDrawFrame(); - proxy->fence(); - - // Capture pixels - - SkImageInfo destinationConfig = - SkImageInfo::Make(size.width(), size.height(), - kRGBA_8888_SkColorType, kPremul_SkAlphaType); - dst->allocPixels(destinationConfig); - sk_memset32((uint32_t*) dst->getPixels(), SK_ColorRED, size.width() * size.height()); - - android::CpuConsumer::LockedBuffer nativeBuffer; - android::status_t retval = cpuConsumer->lockNextBuffer(&nativeBuffer); - if (retval == android::BAD_VALUE) { - SkDebugf("HWUISink::draw() 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. - dst->eraseColor(SK_ColorTRANSPARENT); - return ""; - } else if (retval) { - return SkStringPrintf("Failed to lock buffer to read pixels: %d.", retval); - } - - // 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) { - return "Failed to wrap HWUI buffer in a SkBitmap"; - } - - SK_ALWAYSBREAK(dst->colorType() == kRGBA_8888_SkColorType && - "Destination buffer not RGBA!"); - success = - nativeWrapper.readPixels(destinationConfig, dst->getPixels(), dst->rowBytes(), 0, 0); - if (!success) { - return "Failed to extract pixels from HWUI buffer"; - } - - cpuConsumer->unlockBuffer(nativeBuffer); + renderer.finishDrawing(); + renderer.proxy->fence(); + renderer.capturePixels(dst); return ""; } diff --git a/gyp/utils.gyp b/gyp/utils.gyp index db903017ec..73a9d329e3 100644 --- a/gyp/utils.gyp +++ b/gyp/utils.gyp @@ -139,6 +139,8 @@ 'sources': [ '../src/utils/android/SkAndroidSDKCanvas.h', '../src/utils/android/SkAndroidSDKCanvas.cpp', + '../src/utils/android/SkHwuiRenderer.h', + '../src/utils/android/SkHwuiRenderer.cpp', ], 'direct_dependent_settings': { 'include_dirs': [ diff --git a/src/utils/android/SkHwuiRenderer.cpp b/src/utils/android/SkHwuiRenderer.cpp new file mode 100644 index 0000000000..aac9180df0 --- /dev/null +++ b/src/utils/android/SkHwuiRenderer.cpp @@ -0,0 +1,130 @@ +/* + * 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 "SkHwuiRenderer.h" + +#include "AnimationContext.h" +#include "IContextFactory.h" +#include "SkBitmap.h" +#include "gui/BufferQueue.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); + } +}; + +} + +void SkHwuiRenderer::initialize(SkISize size) { + this->size = size; + 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()); +} + +SkCanvas* SkHwuiRenderer::prepareToDraw() { + this->renderer->prepare(); + this->renderer->clipRect(0, 0, this->size.width(), this->size.height(), + SkRegion::Op::kReplace_Op); + return this->renderer->asSkCanvas(); +} + +void SkHwuiRenderer::finishDrawing() { + 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. +} + +bool SkHwuiRenderer::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/src/utils/android/SkHwuiRenderer.h b/src/utils/android/SkHwuiRenderer.h new file mode 100644 index 0000000000..2e1ce4ebe8 --- /dev/null +++ b/src/utils/android/SkHwuiRenderer.h @@ -0,0 +1,42 @@ +/* + * 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 SkHwuiRenderer_DEFINED +#define SkHwuiRenderer_DEFINED + +#include "DisplayListRenderer.h" +#include "RenderNode.h" +#include "SkTypes.h" +#include "gui/CpuConsumer.h" +#include "gui/IGraphicBufferConsumer.h" +#include "gui/IGraphicBufferProducer.h" +#include "gui/Surface.h" +#include "renderthread/RenderProxy.h" + +class SkBitmap; + +struct SkHwuiRenderer { + 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; + + void initialize(SkISize size); + + /// Returns a canvas to draw into. + SkCanvas* prepareToDraw(); + + void finishDrawing(); + + bool capturePixels(SkBitmap* bmp); +}; + +#endif // SkHwuiRenderer_DEFINED |