blob: 14a4c2879723f54c1b365b966707e4f3ebdf99b4 [file] [log] [blame]
John Reck848f6512018-12-03 13:26:43 -08001/*
2 * Copyright (C) 2018 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
17#include "ReliableSurface.h"
18
Alec Mouri43fe6fc2019-12-23 07:46:19 -080019#include <log/log_main.h>
John Reck848f6512018-12-03 13:26:43 -080020#include <private/android/AHardwareBufferHelpers.h>
Alec Mouri43fe6fc2019-12-23 07:46:19 -080021// TODO: this should be including apex instead.
22#include <vndk/window.h>
John Reck848f6512018-12-03 13:26:43 -080023
24namespace android::uirenderer::renderthread {
25
26// TODO: Re-enable after addressing more of the TODO's
27// With this disabled we won't have a good up-front signal that the surface is no longer valid,
28// however we can at least handle that reactively post-draw. There's just not a good mechanism
29// to propagate this error back to the caller
30constexpr bool DISABLE_BUFFER_PREFETCH = true;
31
Alec Mouri43fe6fc2019-12-23 07:46:19 -080032ReliableSurface::ReliableSurface(ANativeWindow* window) : mWindow(window) {
33 LOG_ALWAYS_FATAL_IF(!mWindow, "Error, unable to wrap a nullptr");
34 ANativeWindow_acquire(mWindow);
John Reck848f6512018-12-03 13:26:43 -080035}
36
37ReliableSurface::~ReliableSurface() {
38 clearReservedBuffer();
Alec Mourif023a322019-11-25 10:02:21 -080039 // Clear out the interceptors for proper hygiene.
40 // As a concrete example, if the underlying ANativeWindow is associated with
41 // an EGLSurface that is still in use, then if we don't clear out the
42 // interceptors then we walk into undefined behavior.
Alec Mouri43fe6fc2019-12-23 07:46:19 -080043 ANativeWindow_setCancelBufferInterceptor(mWindow, nullptr, nullptr);
44 ANativeWindow_setDequeueBufferInterceptor(mWindow, nullptr, nullptr);
45 ANativeWindow_setQueueBufferInterceptor(mWindow, nullptr, nullptr);
46 ANativeWindow_setPerformInterceptor(mWindow, nullptr, nullptr);
47 ANativeWindow_release(mWindow);
John Reck848f6512018-12-03 13:26:43 -080048}
49
Alec Mourif023a322019-11-25 10:02:21 -080050void ReliableSurface::init() {
Alec Mouri43fe6fc2019-12-23 07:46:19 -080051 int result = ANativeWindow_setCancelBufferInterceptor(mWindow, hook_cancelBuffer, this);
Alec Mourif023a322019-11-25 10:02:21 -080052 LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set cancelBuffer interceptor: error = %d",
53 result);
John Reck848f6512018-12-03 13:26:43 -080054
Alec Mouri43fe6fc2019-12-23 07:46:19 -080055 result = ANativeWindow_setDequeueBufferInterceptor(mWindow, hook_dequeueBuffer, this);
Alec Mourif023a322019-11-25 10:02:21 -080056 LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set dequeueBuffer interceptor: error = %d",
57 result);
58
Alec Mouri43fe6fc2019-12-23 07:46:19 -080059 result = ANativeWindow_setQueueBufferInterceptor(mWindow, hook_queueBuffer, this);
Alec Mourif023a322019-11-25 10:02:21 -080060 LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set queueBuffer interceptor: error = %d",
61 result);
62
Alec Mouri43fe6fc2019-12-23 07:46:19 -080063 result = ANativeWindow_setPerformInterceptor(mWindow, hook_perform, this);
Alec Mourif023a322019-11-25 10:02:21 -080064 LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set perform interceptor: error = %d",
65 result);
John Reck848f6512018-12-03 13:26:43 -080066}
67
68int ReliableSurface::reserveNext() {
John Reck59dd2ea2019-07-26 16:51:08 -070069 if constexpr (DISABLE_BUFFER_PREFETCH) {
70 return OK;
71 }
John Reck848f6512018-12-03 13:26:43 -080072 {
73 std::lock_guard _lock{mMutex};
74 if (mReservedBuffer) {
75 ALOGW("reserveNext called but there was already a buffer reserved?");
76 return OK;
77 }
John Reck59dd2ea2019-07-26 16:51:08 -070078 if (mBufferQueueState != OK) {
John Reck848f6512018-12-03 13:26:43 -080079 return UNKNOWN_ERROR;
80 }
81 if (mHasDequeuedBuffer) {
82 return OK;
83 }
John Reck848f6512018-12-03 13:26:43 -080084 }
85
86 // TODO: Update this to better handle when requested dimensions have changed
87 // Currently the driver does this via query + perform but that's after we've already
88 // reserved a buffer. Should we do that logic instead? Or should we drop
89 // the backing Surface to the ground and go full manual on the IGraphicBufferProducer instead?
90
91 int fenceFd = -1;
92 ANativeWindowBuffer* buffer = nullptr;
Alec Mourif023a322019-11-25 10:02:21 -080093
94 // Note that this calls back into our own hooked method.
Alec Mouri43fe6fc2019-12-23 07:46:19 -080095 int result = ANativeWindow_dequeueBuffer(mWindow, &buffer, &fenceFd);
John Reck848f6512018-12-03 13:26:43 -080096
97 {
98 std::lock_guard _lock{mMutex};
99 LOG_ALWAYS_FATAL_IF(mReservedBuffer, "race condition in reserveNext");
100 mReservedBuffer = buffer;
101 mReservedFenceFd.reset(fenceFd);
102 }
103
104 return result;
105}
106
107void ReliableSurface::clearReservedBuffer() {
108 ANativeWindowBuffer* buffer = nullptr;
109 int releaseFd = -1;
110 {
111 std::lock_guard _lock{mMutex};
112 if (mReservedBuffer) {
113 ALOGW("Reserved buffer %p was never used", mReservedBuffer);
114 buffer = mReservedBuffer;
115 releaseFd = mReservedFenceFd.release();
116 }
117 mReservedBuffer = nullptr;
118 mReservedFenceFd.reset();
119 mHasDequeuedBuffer = false;
120 }
121 if (buffer) {
Alec Mourif023a322019-11-25 10:02:21 -0800122 // Note that clearReservedBuffer may be reentrant here, so
123 // mReservedBuffer must be cleared once we reach here to avoid recursing
124 // forever.
Alec Mouri43fe6fc2019-12-23 07:46:19 -0800125 ANativeWindow_cancelBuffer(mWindow, buffer, releaseFd);
John Reck848f6512018-12-03 13:26:43 -0800126 }
127}
128
John Reck848f6512018-12-03 13:26:43 -0800129bool ReliableSurface::isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const {
130 if (!mScratchBuffer || !windowBuffer) {
131 return false;
132 }
133 ANativeWindowBuffer* scratchBuffer =
134 AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
135 return windowBuffer == scratchBuffer;
136}
137
John Reck59dd2ea2019-07-26 16:51:08 -0700138ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer(int error) {
John Reck848f6512018-12-03 13:26:43 -0800139 std::lock_guard _lock{mMutex};
John Reck59dd2ea2019-07-26 16:51:08 -0700140 mBufferQueueState = error;
John Reck848f6512018-12-03 13:26:43 -0800141
142 if (mScratchBuffer) {
143 return AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
144 }
145
Alec Mouri45238012020-01-29 11:04:40 -0800146 AHardwareBuffer_Desc desc = AHardwareBuffer_Desc{
147 .usage = mUsage,
148 .format = mFormat,
149 .width = 1,
150 .height = 1,
151 .layers = 1,
152 .rfu0 = 0,
153 .rfu1 = 0,
154 };
155
156 AHardwareBuffer* newBuffer;
157 int result = AHardwareBuffer_allocate(&desc, &newBuffer);
158
159 if (result != NO_ERROR) {
John Reck848f6512018-12-03 13:26:43 -0800160 // Allocate failed, that sucks
Alec Mouri45238012020-01-29 11:04:40 -0800161 ALOGW("Failed to allocate scratch buffer, error=%d", result);
John Reck848f6512018-12-03 13:26:43 -0800162 return nullptr;
163 }
Alec Mouri45238012020-01-29 11:04:40 -0800164
John Reck848f6512018-12-03 13:26:43 -0800165 mScratchBuffer.reset(newBuffer);
166 return AHardwareBuffer_to_ANativeWindowBuffer(newBuffer);
167}
168
Alec Mourif023a322019-11-25 10:02:21 -0800169int ReliableSurface::hook_dequeueBuffer(ANativeWindow* window,
170 ANativeWindow_dequeueBufferFn dequeueBuffer, void* data,
171 ANativeWindowBuffer** buffer, int* fenceFd) {
172 ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
173 {
174 std::lock_guard _lock{rs->mMutex};
175 if (rs->mReservedBuffer) {
176 *buffer = rs->mReservedBuffer;
177 *fenceFd = rs->mReservedFenceFd.release();
178 rs->mReservedBuffer = nullptr;
179 return OK;
180 }
181 }
John Reck848f6512018-12-03 13:26:43 -0800182
Alec Mourif023a322019-11-25 10:02:21 -0800183 int result = dequeueBuffer(window, buffer, fenceFd);
John Reck848f6512018-12-03 13:26:43 -0800184 if (result != OK) {
Alec Mourif023a322019-11-25 10:02:21 -0800185 ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
186 *buffer = rs->acquireFallbackBuffer(result);
187 *fenceFd = -1;
188 return *buffer ? OK : INVALID_OPERATION;
189 } else {
190 std::lock_guard _lock{rs->mMutex};
191 rs->mHasDequeuedBuffer = true;
John Reck848f6512018-12-03 13:26:43 -0800192 }
John Reck848f6512018-12-03 13:26:43 -0800193 return OK;
194}
195
Alec Mourif023a322019-11-25 10:02:21 -0800196int ReliableSurface::hook_cancelBuffer(ANativeWindow* window,
197 ANativeWindow_cancelBufferFn cancelBuffer, void* data,
198 ANativeWindowBuffer* buffer, int fenceFd) {
199 ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
200 rs->clearReservedBuffer();
201 if (rs->isFallbackBuffer(buffer)) {
202 if (fenceFd > 0) {
203 close(fenceFd);
204 }
205 return OK;
206 }
207 return cancelBuffer(window, buffer, fenceFd);
John Reck848f6512018-12-03 13:26:43 -0800208}
209
Alec Mourif023a322019-11-25 10:02:21 -0800210int ReliableSurface::hook_queueBuffer(ANativeWindow* window,
211 ANativeWindow_queueBufferFn queueBuffer, void* data,
212 ANativeWindowBuffer* buffer, int fenceFd) {
213 ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
214 rs->clearReservedBuffer();
215
216 if (rs->isFallbackBuffer(buffer)) {
217 if (fenceFd > 0) {
218 close(fenceFd);
219 }
220 return OK;
221 }
222
223 return queueBuffer(window, buffer, fenceFd);
John Reck848f6512018-12-03 13:26:43 -0800224}
225
Alec Mourif023a322019-11-25 10:02:21 -0800226int ReliableSurface::hook_perform(ANativeWindow* window, ANativeWindow_performFn perform,
227 void* data, int operation, va_list args) {
John Reck848f6512018-12-03 13:26:43 -0800228 // Drop the reserved buffer if there is one since this (probably) mutated buffer dimensions
229 // TODO: Filter to things that only affect the reserved buffer
230 // TODO: Can we mutate the reserved buffer in some cases?
Alec Mourif023a322019-11-25 10:02:21 -0800231 ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
232 rs->clearReservedBuffer();
John Reck848f6512018-12-03 13:26:43 -0800233
Alec Mourif023a322019-11-25 10:02:21 -0800234 va_list argsCopy;
235 va_copy(argsCopy, args);
236 int result = perform(window, operation, argsCopy);
John Reck848f6512018-12-03 13:26:43 -0800237
Alec Mourif023a322019-11-25 10:02:21 -0800238 {
239 std::lock_guard _lock{rs->mMutex};
240
241 switch (operation) {
242 case ANATIVEWINDOW_PERFORM_SET_USAGE:
243 rs->mUsage = va_arg(args, uint32_t);
244 break;
245 case ANATIVEWINDOW_PERFORM_SET_USAGE64:
246 rs->mUsage = va_arg(args, uint64_t);
247 break;
248 case ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY:
249 /* width */ va_arg(args, uint32_t);
250 /* height */ va_arg(args, uint32_t);
Alec Mouri43fe6fc2019-12-23 07:46:19 -0800251 rs->mFormat = static_cast<AHardwareBuffer_Format>(va_arg(args, int32_t));
Alec Mourif023a322019-11-25 10:02:21 -0800252 break;
253 case ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT:
Alec Mouri43fe6fc2019-12-23 07:46:19 -0800254 rs->mFormat = static_cast<AHardwareBuffer_Format>(va_arg(args, int32_t));
Alec Mourif023a322019-11-25 10:02:21 -0800255 break;
256 }
257 }
John Reck848f6512018-12-03 13:26:43 -0800258 return result;
259}
260
Alec Mouri8d0c5bd22019-08-22 19:20:41 -0700261}; // namespace android::uirenderer::renderthread