1573ae01295241c156ff8548ded283d44864d22d2tomhudson/*
2573ae01295241c156ff8548ded283d44864d22d2tomhudson * Copyright 2015 Google Inc.
3573ae01295241c156ff8548ded283d44864d22d2tomhudson *
4573ae01295241c156ff8548ded283d44864d22d2tomhudson * Use of this source code is governed by a BSD-style license that can be
5573ae01295241c156ff8548ded283d44864d22d2tomhudson * found in the LICENSE file.
6573ae01295241c156ff8548ded283d44864d22d2tomhudson */
7573ae01295241c156ff8548ded283d44864d22d2tomhudson
8573ae01295241c156ff8548ded283d44864d22d2tomhudson#include "SkHwuiRenderer.h"
9573ae01295241c156ff8548ded283d44864d22d2tomhudson
10573ae01295241c156ff8548ded283d44864d22d2tomhudson#include "AnimationContext.h"
11573ae01295241c156ff8548ded283d44864d22d2tomhudson#include "IContextFactory.h"
12573ae01295241c156ff8548ded283d44864d22d2tomhudson#include "SkBitmap.h"
13573ae01295241c156ff8548ded283d44864d22d2tomhudson#include "gui/BufferQueue.h"
14573ae01295241c156ff8548ded283d44864d22d2tomhudson
15573ae01295241c156ff8548ded283d44864d22d2tomhudsonnamespace {
16573ae01295241c156ff8548ded283d44864d22d2tomhudson
17573ae01295241c156ff8548ded283d44864d22d2tomhudson/**
18573ae01295241c156ff8548ded283d44864d22d2tomhudson * Helper class for setting up android::uirenderer::renderthread::RenderProxy.
19573ae01295241c156ff8548ded283d44864d22d2tomhudson */
20573ae01295241c156ff8548ded283d44864d22d2tomhudsonclass ContextFactory : public android::uirenderer::IContextFactory {
21573ae01295241c156ff8548ded283d44864d22d2tomhudsonpublic:
22573ae01295241c156ff8548ded283d44864d22d2tomhudson    android::uirenderer::AnimationContext* createAnimationContext
23573ae01295241c156ff8548ded283d44864d22d2tomhudson        (android::uirenderer::renderthread::TimeLord& clock) override {
24573ae01295241c156ff8548ded283d44864d22d2tomhudson        return new android::uirenderer::AnimationContext(clock);
25573ae01295241c156ff8548ded283d44864d22d2tomhudson    }
26573ae01295241c156ff8548ded283d44864d22d2tomhudson};
27573ae01295241c156ff8548ded283d44864d22d2tomhudson
28573ae01295241c156ff8548ded283d44864d22d2tomhudson}
29573ae01295241c156ff8548ded283d44864d22d2tomhudson
30573ae01295241c156ff8548ded283d44864d22d2tomhudsonvoid SkHwuiRenderer::initialize(SkISize size) {
31573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->size = size;
32573ae01295241c156ff8548ded283d44864d22d2tomhudson    android::BufferQueue::createBufferQueue(&this->producer, &this->consumer);
33573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->cpuConsumer = new android::CpuConsumer(this->consumer, 1);
34573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->cpuConsumer->setName(android::String8("SkiaBenchmarkClient"));
35573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->cpuConsumer->setDefaultBufferSize(size.width(), size.height());
36573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->androidSurface = new android::Surface(this->producer);
37573ae01295241c156ff8548ded283d44864d22d2tomhudson    native_window_set_buffers_dimensions(this->androidSurface.get(),
38573ae01295241c156ff8548ded283d44864d22d2tomhudson                                         size.width(), size.height());
39573ae01295241c156ff8548ded283d44864d22d2tomhudson    native_window_set_buffers_format(this->androidSurface.get(),
40573ae01295241c156ff8548ded283d44864d22d2tomhudson                                     android::PIXEL_FORMAT_RGBA_8888);
41573ae01295241c156ff8548ded283d44864d22d2tomhudson    native_window_set_usage(this->androidSurface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
42573ae01295241c156ff8548ded283d44864d22d2tomhudson                                           GRALLOC_USAGE_SW_WRITE_NEVER |
43573ae01295241c156ff8548ded283d44864d22d2tomhudson                                           GRALLOC_USAGE_HW_RENDER);
44573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->rootNode.reset(new android::uirenderer::RenderNode());
45573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->rootNode->incStrong(nullptr);
46573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->rootNode->mutateStagingProperties().setLeftTopRightBottom
47573ae01295241c156ff8548ded283d44864d22d2tomhudson        (0, 0, size.width(), size.height());
48573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->rootNode->mutateStagingProperties().setClipToBounds(false);
49573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
50573ae01295241c156ff8548ded283d44864d22d2tomhudson    ContextFactory factory;
51573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->proxy.reset
52573ae01295241c156ff8548ded283d44864d22d2tomhudson        (new android::uirenderer::renderthread::RenderProxy(false, this->rootNode, &factory));
53573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->proxy->loadSystemProperties();
54573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->proxy->initialize(this->androidSurface.get());
55573ae01295241c156ff8548ded283d44864d22d2tomhudson    float lightX = size.width() / 2.0f;
56573ae01295241c156ff8548ded283d44864d22d2tomhudson    android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
57c8cae184262251418ca3f8a70952805980121d0cDerek Sollenberger    this->proxy->setup(size.width(), size.height(), 800.0f,
58573ae01295241c156ff8548ded283d44864d22d2tomhudson                         255 * 0.075f, 255 * 0.15f);
59c8cae184262251418ca3f8a70952805980121d0cDerek Sollenberger    this->proxy->setLightCenter(lightVector);
60d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->canvas.reset(new android::uirenderer::DisplayListCanvas());
61d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->canvas->setViewport(size.width(), size.height());
62573ae01295241c156ff8548ded283d44864d22d2tomhudson}
63573ae01295241c156ff8548ded283d44864d22d2tomhudson
64573ae01295241c156ff8548ded283d44864d22d2tomhudsonSkCanvas* SkHwuiRenderer::prepareToDraw() {
65d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->canvas->prepare();
66d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->canvas->clipRect(0, 0, this->size.width(), this->size.height(),
67d7c677104a6847ca59d36a1103d57478399209cctomhudson                           SkRegion::Op::kReplace_Op);
68d7c677104a6847ca59d36a1103d57478399209cctomhudson    return this->canvas->asSkCanvas();
69573ae01295241c156ff8548ded283d44864d22d2tomhudson}
70573ae01295241c156ff8548ded283d44864d22d2tomhudson
71573ae01295241c156ff8548ded283d44864d22d2tomhudsonvoid SkHwuiRenderer::finishDrawing() {
72d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->canvas->finish();
73d7c677104a6847ca59d36a1103d57478399209cctomhudson    this->rootNode->setStagingDisplayList(this->canvas->finishRecording());
74573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->proxy->syncAndDrawFrame();
75573ae01295241c156ff8548ded283d44864d22d2tomhudson    // Surprisingly, calling this->proxy->fence() here appears to make no difference to
76573ae01295241c156ff8548ded283d44864d22d2tomhudson    // the timings we record.
77573ae01295241c156ff8548ded283d44864d22d2tomhudson}
78573ae01295241c156ff8548ded283d44864d22d2tomhudson
79573ae01295241c156ff8548ded283d44864d22d2tomhudsonbool SkHwuiRenderer::capturePixels(SkBitmap* bmp) {
80573ae01295241c156ff8548ded283d44864d22d2tomhudson    SkImageInfo destinationConfig =
81573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkImageInfo::Make(this->size.width(), this->size.height(),
82573ae01295241c156ff8548ded283d44864d22d2tomhudson                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);
83573ae01295241c156ff8548ded283d44864d22d2tomhudson    bmp->allocPixels(destinationConfig);
84573ae01295241c156ff8548ded283d44864d22d2tomhudson    sk_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
85573ae01295241c156ff8548ded283d44864d22d2tomhudson                this->size.width() * this->size.height());
86573ae01295241c156ff8548ded283d44864d22d2tomhudson
87573ae01295241c156ff8548ded283d44864d22d2tomhudson    android::CpuConsumer::LockedBuffer nativeBuffer;
88573ae01295241c156ff8548ded283d44864d22d2tomhudson    android::status_t retval = this->cpuConsumer->lockNextBuffer(&nativeBuffer);
89573ae01295241c156ff8548ded283d44864d22d2tomhudson    if (retval == android::BAD_VALUE) {
90573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkDebugf("write_canvas_png() got no buffer; returning transparent");
91573ae01295241c156ff8548ded283d44864d22d2tomhudson        // No buffer ready to read - commonly triggered by dm sending us
92573ae01295241c156ff8548ded283d44864d22d2tomhudson        // a no-op source, or calling code that doesn't do anything on this
93573ae01295241c156ff8548ded283d44864d22d2tomhudson        // backend.
94573ae01295241c156ff8548ded283d44864d22d2tomhudson        bmp->eraseColor(SK_ColorTRANSPARENT);
95573ae01295241c156ff8548ded283d44864d22d2tomhudson        return false;
96573ae01295241c156ff8548ded283d44864d22d2tomhudson    } else if (retval) {
97573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkDebugf("Failed to lock buffer to read pixels: %d.", retval);
98573ae01295241c156ff8548ded283d44864d22d2tomhudson        return false;
99573ae01295241c156ff8548ded283d44864d22d2tomhudson    }
100573ae01295241c156ff8548ded283d44864d22d2tomhudson
101573ae01295241c156ff8548ded283d44864d22d2tomhudson    // Move the pixels into the destination SkBitmap
102573ae01295241c156ff8548ded283d44864d22d2tomhudson
103573ae01295241c156ff8548ded283d44864d22d2tomhudson    SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 &&
104573ae01295241c156ff8548ded283d44864d22d2tomhudson                   "Native buffer not RGBA!");
105573ae01295241c156ff8548ded283d44864d22d2tomhudson    SkImageInfo nativeConfig =
106573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
107573ae01295241c156ff8548ded283d44864d22d2tomhudson                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);
108573ae01295241c156ff8548ded283d44864d22d2tomhudson
109573ae01295241c156ff8548ded283d44864d22d2tomhudson    // Android stride is in pixels, Skia stride is in bytes
110573ae01295241c156ff8548ded283d44864d22d2tomhudson    SkBitmap nativeWrapper;
111573ae01295241c156ff8548ded283d44864d22d2tomhudson    bool success =
112573ae01295241c156ff8548ded283d44864d22d2tomhudson        nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
113573ae01295241c156ff8548ded283d44864d22d2tomhudson    if (!success) {
114573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
115573ae01295241c156ff8548ded283d44864d22d2tomhudson        return false;
116573ae01295241c156ff8548ded283d44864d22d2tomhudson    }
117573ae01295241c156ff8548ded283d44864d22d2tomhudson
118573ae01295241c156ff8548ded283d44864d22d2tomhudson    SK_ALWAYSBREAK(bmp->colorType() == kRGBA_8888_SkColorType &&
119573ae01295241c156ff8548ded283d44864d22d2tomhudson                   "Destination buffer not RGBA!");
120573ae01295241c156ff8548ded283d44864d22d2tomhudson    success =
121573ae01295241c156ff8548ded283d44864d22d2tomhudson        nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0, 0);
122573ae01295241c156ff8548ded283d44864d22d2tomhudson    if (!success) {
123573ae01295241c156ff8548ded283d44864d22d2tomhudson        SkDebugf("Failed to extract pixels from HWUI buffer");
124573ae01295241c156ff8548ded283d44864d22d2tomhudson        return false;
125573ae01295241c156ff8548ded283d44864d22d2tomhudson    }
126573ae01295241c156ff8548ded283d44864d22d2tomhudson
127573ae01295241c156ff8548ded283d44864d22d2tomhudson    this->cpuConsumer->unlockBuffer(nativeBuffer);
128573ae01295241c156ff8548ded283d44864d22d2tomhudson
129573ae01295241c156ff8548ded283d44864d22d2tomhudson    return true;
130573ae01295241c156ff8548ded283d44864d22d2tomhudson}
131573ae01295241c156ff8548ded283d44864d22d2tomhudson
132