blob: 84aae75323fd9ce1b70ac6bdba74eedf8034ac2c [file] [log] [blame]
Tom Hudsonb2f5bd22015-10-15 16:41:55 -04001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include "TestWindowContext.h"
17
18#include "AnimationContext.h"
19#include "DisplayListCanvas.h"
20#include "IContextFactory.h"
21#include "RenderNode.h"
22#include "SkTypes.h"
23#include "gui/BufferQueue.h"
24#include "gui/CpuConsumer.h"
25#include "gui/IGraphicBufferConsumer.h"
26#include "gui/IGraphicBufferProducer.h"
27#include "gui/Surface.h"
28#include "renderthread/RenderProxy.h"
29
30
31namespace {
32
33/**
34 * Helper class for setting up android::uirenderer::renderthread::RenderProxy.
35 */
36class ContextFactory : public android::uirenderer::IContextFactory {
37public:
38 android::uirenderer::AnimationContext* createAnimationContext
39 (android::uirenderer::renderthread::TimeLord& clock) override {
40 return new android::uirenderer::AnimationContext(clock);
41 }
42};
43
44} // anonymous namespace
45
46namespace android {
47namespace uirenderer {
48
49/**
50 Android strong pointers (android::sp) can't hold forward-declared classes,
51 so we have to use pointer-to-implementation here if we want to hide the
52 details from our non-framework users.
53*/
54
55class TestWindowContext::TestWindowData {
56
57public:
58
59 TestWindowData(SkISize size) : mSize(size) {
60 android::BufferQueue::createBufferQueue(&mProducer, &mConsumer);
61 mCpuConsumer = new android::CpuConsumer(mConsumer, 1);
62 mCpuConsumer->setName(android::String8("TestWindowContext"));
63 mCpuConsumer->setDefaultBufferSize(mSize.width(), mSize.height());
64 mAndroidSurface = new android::Surface(mProducer);
65 native_window_set_buffers_dimensions(mAndroidSurface.get(),
66 mSize.width(), mSize.height());
67 native_window_set_buffers_format(mAndroidSurface.get(),
68 android::PIXEL_FORMAT_RGBA_8888);
69 native_window_set_usage(mAndroidSurface.get(),
70 GRALLOC_USAGE_SW_READ_OFTEN |
71 GRALLOC_USAGE_SW_WRITE_NEVER |
72 GRALLOC_USAGE_HW_RENDER);
73 mRootNode.reset(new android::uirenderer::RenderNode());
74 mRootNode->incStrong(nullptr);
75 mRootNode->mutateStagingProperties().setLeftTopRightBottom
76 (0, 0, mSize.width(), mSize.height());
77 mRootNode->mutateStagingProperties().setClipToBounds(false);
78 mRootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);
79 ContextFactory factory;
80 mProxy.reset
81 (new android::uirenderer::renderthread::RenderProxy(false,
82 mRootNode.get(),
83 &factory));
84 mProxy->loadSystemProperties();
85 mProxy->initialize(mAndroidSurface.get());
86 float lightX = mSize.width() / 2.0f;
87 android::uirenderer::Vector3 lightVector { lightX, -200.0f, 800.0f };
88 mProxy->setup(mSize.width(), mSize.height(), 800.0f,
89 255 * 0.075f, 255 * 0.15f);
90 mProxy->setLightCenter(lightVector);
91 mCanvas.reset(new
92 android::uirenderer::DisplayListCanvas(mSize.width(),
93 mSize.height()));
94 }
95
96 SkCanvas* prepareToDraw() {
97 //mCanvas->reset(mSize.width(), mSize.height());
98 mCanvas->clipRect(0, 0, mSize.width(), mSize.height(),
99 SkRegion::Op::kReplace_Op);
100 return mCanvas->asSkCanvas();
101 }
102
103 void finishDrawing() {
104 mRootNode->setStagingDisplayList(mCanvas->finishRecording());
105 mProxy->syncAndDrawFrame();
106 // Surprisingly, calling mProxy->fence() here appears to make no difference to
107 // the timings we record.
108 }
109
110 void fence() {
111 mProxy->fence();
112 }
113
114 bool capturePixels(SkBitmap* bmp) {
115 SkImageInfo destinationConfig =
116 SkImageInfo::Make(mSize.width(), mSize.height(),
117 kRGBA_8888_SkColorType, kPremul_SkAlphaType);
118 bmp->allocPixels(destinationConfig);
119 sk_memset32((uint32_t*) bmp->getPixels(), SK_ColorRED,
120 mSize.width() * mSize.height());
121
122 android::CpuConsumer::LockedBuffer nativeBuffer;
123 android::status_t retval = mCpuConsumer->lockNextBuffer(&nativeBuffer);
124 if (retval == android::BAD_VALUE) {
125 SkDebugf("write_canvas_png() got no buffer; returning transparent");
126 // No buffer ready to read - commonly triggered by dm sending us
127 // a no-op source, or calling code that doesn't do anything on this
128 // backend.
129 bmp->eraseColor(SK_ColorTRANSPARENT);
130 return false;
131 } else if (retval) {
132 SkDebugf("Failed to lock buffer to read pixels: %d.", retval);
133 return false;
134 }
135
136 // Move the pixels into the destination SkBitmap
137
138 SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 &&
139 "Native buffer not RGBA!");
140 SkImageInfo nativeConfig =
141 SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
142 kRGBA_8888_SkColorType, kPremul_SkAlphaType);
143
144 // Android stride is in pixels, Skia stride is in bytes
145 SkBitmap nativeWrapper;
146 bool success =
147 nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
148 if (!success) {
149 SkDebugf("Failed to wrap HWUI buffer in a SkBitmap");
150 return false;
151 }
152
153 SK_ALWAYSBREAK(bmp->colorType() == kRGBA_8888_SkColorType &&
154 "Destination buffer not RGBA!");
155 success =
156 nativeWrapper.readPixels(destinationConfig, bmp->getPixels(), bmp->rowBytes(), 0, 0);
157 if (!success) {
158 SkDebugf("Failed to extract pixels from HWUI buffer");
159 return false;
160 }
161
162 mCpuConsumer->unlockBuffer(nativeBuffer);
163
164 return true;
165 }
166
167private:
168
169 std::unique_ptr<android::uirenderer::RenderNode> mRootNode;
170 std::unique_ptr<android::uirenderer::renderthread::RenderProxy> mProxy;
171 std::unique_ptr<android::uirenderer::DisplayListCanvas> mCanvas;
172 android::sp<android::IGraphicBufferProducer> mProducer;
173 android::sp<android::IGraphicBufferConsumer> mConsumer;
174 android::sp<android::CpuConsumer> mCpuConsumer;
175 android::sp<android::Surface> mAndroidSurface;
176 SkISize mSize;
177};
178
179
180TestWindowContext::TestWindowContext() :
181 mData (nullptr) { }
182
183void TestWindowContext::initialize(int width, int height) {
184 mData = new TestWindowData(SkISize::Make(width, height));
185}
186
187SkCanvas* TestWindowContext::prepareToDraw() {
188 return mData ? mData->prepareToDraw() : nullptr;
189}
190
191void TestWindowContext::finishDrawing() {
192 if (mData) {
193 mData->finishDrawing();
194 }
195}
196
197void TestWindowContext::fence() {
198 if (mData) {
199 mData->fence();
200 }
201}
202
203bool TestWindowContext::capturePixels(SkBitmap* bmp) {
204 return mData ? mData->capturePixels(bmp) : false;
205}
206
207} // namespace uirenderer
208} // namespace android
209