diff options
author | tomhudson <tomhudson@google.com> | 2015-03-27 12:22:01 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-27 12:22:01 -0700 |
commit | 573ae01295241c156ff8548ded283d44864d22d2 (patch) | |
tree | d141b747025817302060b9013ece827e94ffc87c /src/utils | |
parent | 255dcd11992ebe74eb54202c48cf5394d33a8ce6 (diff) |
Move HWUI boilerplate into utils/android
Duplicate code from the HWUI backends for DM and nanobench
moves into a single place, saving a hundred lines or more of
cut-and-paste.
There's some indication that this increases the incidence of
SkCanvas "Unable to find device for layer." warnings, but no
clear degradation in test results.
R=djsollen@google.com,mtklein@google.com
BUG=skia:3589
Review URL: https://codereview.chromium.org/1036303002
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/android/SkHwuiRenderer.cpp | 130 | ||||
-rw-r--r-- | src/utils/android/SkHwuiRenderer.h | 42 |
2 files changed, 172 insertions, 0 deletions
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 |