blob: 660baffa3ac951e40f91a60cad69ede5299dc265 [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
108void RenderSurface::setProtected(bool useProtected) {
109 uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER;
110 if (useProtected) {
111 usageFlags |= GRALLOC_USAGE_PROTECTED;
112 }
113 const int status = native_window_set_usage(mNativeWindow.get(), usageFlags);
114 ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status);
Peiyong Lin52010312019-05-02 14:22:16 -0700115 if (status == NO_ERROR) {
116 mProtected = useProtected;
117 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700118}
119
120status_t RenderSurface::beginFrame(bool mustRecompose) {
121 return mDisplaySurface->beginFrame(mustRecompose);
122}
123
Lloyd Pique66d68602019-02-13 14:23:31 -0800124void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700125 DisplaySurface::CompositionType compositionType;
Lloyd Pique66d68602019-02-13 14:23:31 -0800126 if (usesClientComposition && usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700127 compositionType = DisplaySurface::COMPOSITION_MIXED;
Lloyd Pique66d68602019-02-13 14:23:31 -0800128 } else if (usesClientComposition) {
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800129 compositionType = DisplaySurface::COMPOSITION_GPU;
Lloyd Pique66d68602019-02-13 14:23:31 -0800130 } else if (usesDeviceComposition) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700131 compositionType = DisplaySurface::COMPOSITION_HWC;
132 } else {
133 // Nothing to do -- when turning the screen off we get a frame like
Peiyong Linf3ffc4e2019-12-13 00:46:24 -0800134 // this. Call it a HWC frame since we won't be doing any GPU work but
Lloyd Pique31cb2942018-10-19 17:23:03 -0700135 // will do a prepare/set cycle.
136 compositionType = DisplaySurface::COMPOSITION_HWC;
137 }
Lloyd Pique66d68602019-02-13 14:23:31 -0800138
139 if (status_t result = mDisplaySurface->prepareFrame(compositionType); result != NO_ERROR) {
140 ALOGE("updateCompositionType failed for %s: %d (%s)", mDisplay.getName().c_str(), result,
141 strerror(-result));
142 }
Lloyd Pique31cb2942018-10-19 17:23:03 -0700143}
144
Alec Mouri6338c9d2019-02-07 16:57:51 -0800145sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) {
146 ATRACE_CALL();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700147 int fd = -1;
148 ANativeWindowBuffer* buffer = nullptr;
149
150 status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
151
152 if (result != NO_ERROR) {
153 ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
154 mDisplay.getName().c_str(), result);
155 // Return fast here as we can't do much more - any rendering we do
156 // now will just be wrong.
157 return mGraphicBuffer;
158 }
159
160 ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
161 mGraphicBuffer->getNativeBuffer()->handle);
162 mGraphicBuffer = GraphicBuffer::from(buffer);
163
Alec Mouri6338c9d2019-02-07 16:57:51 -0800164 *bufferFence = base::unique_fd(fd);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700165
166 return mGraphicBuffer;
167}
168
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700169void RenderSurface::queueBuffer(base::unique_fd readyFence) {
Lloyd Pique66d68602019-02-13 14:23:31 -0800170 auto& state = mDisplay.getState();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700171
Lloyd Pique66d68602019-02-13 14:23:31 -0800172 if (state.usesClientComposition || state.flipClientTarget) {
Lloyd Pique31cb2942018-10-19 17:23:03 -0700173 // hasFlipClientTargetRequest could return true even if we haven't
174 // dequeued a buffer before. Try dequeueing one if we don't have a
175 // buffer ready.
176 if (mGraphicBuffer == nullptr) {
177 ALOGI("Attempting to queue a client composited buffer without one "
178 "previously dequeued for display [%s]. Attempting to dequeue "
179 "a scratch buffer now",
180 mDisplay.getName().c_str());
181 // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
182 // after a successful call to queueBuffer, or if dequeueBuffer has
183 // never been called.
Alec Mouri6338c9d2019-02-07 16:57:51 -0800184 base::unique_fd unused;
185 dequeueBuffer(&unused);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700186 }
187
188 if (mGraphicBuffer == nullptr) {
189 ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str());
190 } else {
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000191 status_t result =
192 mNativeWindow->queueBuffer(mNativeWindow.get(),
193 mGraphicBuffer->getNativeBuffer(), dup(readyFence));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700194 if (result != NO_ERROR) {
195 ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
196 result);
197 // We risk blocking on dequeueBuffer if the primary display failed
198 // to queue up its buffer, so crash here.
199 if (!mDisplay.isVirtual()) {
200 LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
201 } else {
202 mNativeWindow->cancelBuffer(mNativeWindow.get(),
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000203 mGraphicBuffer->getNativeBuffer(), dup(readyFence));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700204 }
205 }
206
Lloyd Pique31cb2942018-10-19 17:23:03 -0700207 mGraphicBuffer = nullptr;
208 }
209 }
210
211 status_t result = mDisplaySurface->advanceFrame();
212 if (result != NO_ERROR) {
213 ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result);
214 }
215}
216
217void RenderSurface::onPresentDisplayCompleted() {
218 mDisplaySurface->onFrameCommitted();
219}
220
Lloyd Pique31cb2942018-10-19 17:23:03 -0700221void RenderSurface::flip() {
222 mPageFlipCount++;
223}
224
225void RenderSurface::dump(std::string& out) const {
226 using android::base::StringAppendF;
227
228 out.append(" Composition RenderSurface State:");
229
230 out.append("\n ");
231
232 dumpVal(out, "size", mSize);
233 StringAppendF(&out, "ANativeWindow=%p (format %d) ", mNativeWindow.get(),
234 ANativeWindow_getFormat(mNativeWindow.get()));
235 dumpVal(out, "flips", mPageFlipCount);
236 out.append("\n");
237
238 String8 surfaceDump;
239 mDisplaySurface->dumpAsString(surfaceDump);
240 out.append(surfaceDump);
241}
242
243std::uint32_t RenderSurface::getPageFlipCount() const {
244 return mPageFlipCount;
245}
246
247void RenderSurface::setPageFlipCountForTest(std::uint32_t count) {
248 mPageFlipCount = count;
249}
250
251void RenderSurface::setSizeForTest(const ui::Size& size) {
252 mSize = size;
253}
254
255sp<GraphicBuffer>& RenderSurface::mutableGraphicBufferForTest() {
256 return mGraphicBuffer;
257}
258
Lloyd Pique31cb2942018-10-19 17:23:03 -0700259} // namespace impl
260} // namespace android::compositionengine