blob: b59f9a8edc0a5f78cd12479c45de8eaf83d0f4a8 [file] [log] [blame]
Lloyd Pique31cb2942018-10-19 17:23:03 -07001/*
2 * Copyright 2019 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
Alec Mouri6338c9d2019-02-07 16:57:51 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Lloyd Pique31cb2942018-10-19 17:23:03 -070019#include <android-base/stringprintf.h>
20#include <android/native_window.h>
21#include <compositionengine/CompositionEngine.h>
22#include <compositionengine/Display.h>
23#include <compositionengine/DisplaySurface.h>
24#include <compositionengine/RenderSurfaceCreationArgs.h>
25#include <compositionengine/impl/DumpHelpers.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080026#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070027#include <compositionengine/impl/RenderSurface.h>
Lloyd Pique3b5a69e2020-01-16 17:51:01 -080028
Lloyd Pique31cb2942018-10-19 17:23:03 -070029#include <log/log.h>
30#include <renderengine/RenderEngine.h>
31#include <sync/sync.h>
32#include <system/window.h>
33#include <ui/GraphicBuffer.h>
34#include <ui/Rect.h>
Alec Mouri6338c9d2019-02-07 16:57:51 -080035#include <utils/Trace.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070036
Lloyd Pique3b5a69e2020-01-16 17:51:01 -080037// TODO(b/129481165): remove the #pragma below and fix conversion issues
38#pragma clang diagnostic push
39#pragma clang diagnostic ignored "-Wconversion"
40
Lloyd Pique31cb2942018-10-19 17:23:03 -070041#include "DisplayHardware/HWComposer.h"
42
Lloyd Pique3b5a69e2020-01-16 17:51:01 -080043// TODO(b/129481165): remove the #pragma below and fix conversion issues
44#pragma clang diagnostic pop // ignored "-Wconversion"
45
Lloyd Pique31cb2942018-10-19 17:23:03 -070046namespace android::compositionengine {
47
48RenderSurface::~RenderSurface() = default;
49
50namespace impl {
51
52std::unique_ptr<compositionengine::RenderSurface> createRenderSurface(
53 const compositionengine::CompositionEngine& compositionEngine,
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070054 compositionengine::Display& display,
55 const compositionengine::RenderSurfaceCreationArgs& args) {
56 return std::make_unique<RenderSurface>(compositionEngine, display, args);
Lloyd Pique31cb2942018-10-19 17:23:03 -070057}
58
59RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display,
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070060 const RenderSurfaceCreationArgs& args)
Lloyd Pique31cb2942018-10-19 17:23:03 -070061 : mCompositionEngine(compositionEngine),
62 mDisplay(display),
63 mNativeWindow(args.nativeWindow),
64 mDisplaySurface(args.displaySurface),
chaviw8beb4142019-04-11 13:09:05 -070065 mSize(args.displayWidth, args.displayHeight) {
66 LOG_ALWAYS_FATAL_IF(!mNativeWindow);
67}
Lloyd Pique31cb2942018-10-19 17:23:03 -070068
chaviw8beb4142019-04-11 13:09:05 -070069RenderSurface::~RenderSurface() {
70 ANativeWindow* const window = mNativeWindow.get();
71 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
72}
Lloyd Pique31cb2942018-10-19 17:23:03 -070073
74bool RenderSurface::isValid() const {
75 return mSize.isValid();
76}
77
78void RenderSurface::initialize() {
79 ANativeWindow* const window = mNativeWindow.get();
80
81 int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
82 ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status);
83 status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
84 ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status);
85 status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER);
86 ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status);
87}
88
89const ui::Size& RenderSurface::getSize() const {
90 return mSize;
91}
92
93const sp<Fence>& RenderSurface::getClientTargetAcquireFence() const {
94 return mDisplaySurface->getClientTargetAcquireFence();
95}
96
97void RenderSurface::setDisplaySize(const ui::Size& size) {
Lloyd Pique0a456232020-01-16 17:51:13 -080098 mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
99 static_cast<uint32_t>(size.height));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700100 mSize = size;
101}
102
103void RenderSurface::setBufferDataspace(ui::Dataspace dataspace) {
104 native_window_set_buffers_data_space(mNativeWindow.get(),
105 static_cast<android_dataspace>(dataspace));
106}
107
Peiyong Lindfc3f7c2020-05-07 20:15:50 -0700108void RenderSurface::setBufferPixelFormat(ui::PixelFormat pixelFormat) {
109 native_window_set_buffers_format(mNativeWindow.get(), static_cast<int32_t>(pixelFormat));
110}
111
Lloyd Pique31cb2942018-10-19 17:23:03 -0700112void RenderSurface::setProtected(bool useProtected) {
113 uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER;
114 if (useProtected) {
115 usageFlags |= GRALLOC_USAGE_PROTECTED;
116 }
117 const int status = native_window_set_usage(mNativeWindow.get(), usageFlags);
118 ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status);
Peiyong Lin52010312019-05-02 14:22:16 -0700119 if (status == NO_ERROR) {
120 mProtected = useProtected;
121 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700122}
123
124status_t RenderSurface::beginFrame(bool mustRecompose) {
125 return mDisplaySurface->beginFrame(mustRecompose);
126}
127
Lloyd Pique66d68602019-02-13 14:23:31 -0800128void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700129 DisplaySurface::CompositionType compositionType;
Lloyd Pique66d68602019-02-13 14:23:31 -0800130 if (usesClientComposition && usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700131 compositionType = DisplaySurface::COMPOSITION_MIXED;
Lloyd Pique66d68602019-02-13 14:23:31 -0800132 } else if (usesClientComposition) {
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800133 compositionType = DisplaySurface::COMPOSITION_GPU;
Lloyd Pique66d68602019-02-13 14:23:31 -0800134 } else if (usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700135 compositionType = DisplaySurface::COMPOSITION_HWC;
136 } else {
137 // Nothing to do -- when turning the screen off we get a frame like
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800138 // this. Call it a HWC frame since we won't be doing any GPU work but
Lloyd Pique31cb2942018-10-19 17:23:03 -0700139 // will do a prepare/set cycle.
140 compositionType = DisplaySurface::COMPOSITION_HWC;
141 }
Lloyd Pique66d68602019-02-13 14:23:31 -0800142
143 if (status_t result = mDisplaySurface->prepareFrame(compositionType); result != NO_ERROR) {
144 ALOGE("updateCompositionType failed for %s: %d (%s)", mDisplay.getName().c_str(), result,
145 strerror(-result));
146 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700147}
148
Alec Mouri6338c9d2019-02-07 16:57:51 -0800149sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
150 ATRACE_CALL();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700151 int fd = -1;
152 ANativeWindowBuffer* buffer = nullptr;
153
154 status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
155
156 if (result != NO_ERROR) {
157 ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
158 mDisplay.getName().c_str(), result);
159 // Return fast here as we can't do much more - any rendering we do
160 // now will just be wrong.
161 return mGraphicBuffer;
162 }
163
164 ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
165 mGraphicBuffer->getNativeBuffer()->handle);
166 mGraphicBuffer = GraphicBuffer::from(buffer);
167
Alec Mouri6338c9d2019-02-07 16:57:51 -0800168 *bufferFence = base::unique_fd(fd);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700169
170 return mGraphicBuffer;
171}
172
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700173void RenderSurface::queueBuffer(base::unique_fd readyFence) {
Lloyd Pique66d68602019-02-13 14:23:31 -0800174 auto& state = mDisplay.getState();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700175
Lloyd Pique66d68602019-02-13 14:23:31 -0800176 if (state.usesClientComposition || state.flipClientTarget) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700177 // hasFlipClientTargetRequest could return true even if we haven't
178 // dequeued a buffer before. Try dequeueing one if we don't have a
179 // buffer ready.
180 if (mGraphicBuffer == nullptr) {
181 ALOGI("Attempting to queue a client composited buffer without one "
182 "previously dequeued for display [%s]. Attempting to dequeue "
183 "a scratch buffer now",
184 mDisplay.getName().c_str());
185 // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
186 // after a successful call to queueBuffer, or if dequeueBuffer has
187 // never been called.
Alec Mouri6338c9d2019-02-07 16:57:51 -0800188 base::unique_fd unused;
189 dequeueBuffer(&unused);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190 }
191
192 if (mGraphicBuffer == nullptr) {
193 ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str());
194 } else {
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000195 status_t result =
196 mNativeWindow->queueBuffer(mNativeWindow.get(),
197 mGraphicBuffer->getNativeBuffer(), dup(readyFence));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700198 if (result != NO_ERROR) {
199 ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
200 result);
201 // We risk blocking on dequeueBuffer if the primary display failed
202 // to queue up its buffer, so crash here.
203 if (!mDisplay.isVirtual()) {
204 LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
205 } else {
206 mNativeWindow->cancelBuffer(mNativeWindow.get(),
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000207 mGraphicBuffer->getNativeBuffer(), dup(readyFence));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700208 }
209 }
210
Lloyd Pique31cb2942018-10-19 17:23:03 -0700211 mGraphicBuffer = nullptr;
212 }
213 }
214
215 status_t result = mDisplaySurface->advanceFrame();
216 if (result != NO_ERROR) {
217 ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result);
218 }
219}
220
221void RenderSurface::onPresentDisplayCompleted() {
222 mDisplaySurface->onFrameCommitted();
223}
224
Lloyd Pique31cb2942018-10-19 17:23:03 -0700225void RenderSurface::flip() {
226 mPageFlipCount++;
227}
228
229void RenderSurface::dump(std::string& out) const {
230 using android::base::StringAppendF;
231
232 out.append(" Composition RenderSurface State:");
233
234 out.append("\n ");
235
236 dumpVal(out, "size", mSize);
237 StringAppendF(&out, "ANativeWindow=%p (format %d) ", mNativeWindow.get(),
238 ANativeWindow_getFormat(mNativeWindow.get()));
239 dumpVal(out, "flips", mPageFlipCount);
240 out.append("\n");
241
242 String8 surfaceDump;
243 mDisplaySurface->dumpAsString(surfaceDump);
244 out.append(surfaceDump);
245}
246
247std::uint32_t RenderSurface::getPageFlipCount() const {
248 return mPageFlipCount;
249}
250
251void RenderSurface::setPageFlipCountForTest(std::uint32_t count) {
252 mPageFlipCount = count;
253}
254
255void RenderSurface::setSizeForTest(const ui::Size& size) {
256 mSize = size;
257}
258
259sp<GraphicBuffer>& RenderSurface::mutableGraphicBufferForTest() {
260 return mGraphicBuffer;
261}
262
Lloyd Pique31cb2942018-10-19 17:23:03 -0700263} // namespace impl
264} // namespace android::compositionengine