blob: 0344fd3d3ae1a7a62fc85b0f689f2e3af48800cb [file] [log] [blame]
Sungtak Leefce527c2021-03-20 01:24:41 -07001/*
2 * Copyright (C) 2021 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//#define LOG_NDEBUG 0
18#define LOG_TAG "C2FenceFactory"
Lubin Yin92427a52022-04-18 16:57:39 -070019#include <cutils/native_handle.h>
Sungtak Leefce527c2021-03-20 01:24:41 -070020#include <utils/Log.h>
Lubin Yin92427a52022-04-18 16:57:39 -070021#include <ui/Fence.h>
Sungtak Leefce527c2021-03-20 01:24:41 -070022
23#include <C2FenceFactory.h>
24#include <C2SurfaceSyncObj.h>
25
Lubin Yin92427a52022-04-18 16:57:39 -070026#define MAX_FENCE_FDS 1
27
Sungtak Leefce527c2021-03-20 01:24:41 -070028class C2Fence::Impl {
29public:
Lubin Yin92427a52022-04-18 16:57:39 -070030 enum type_t : uint32_t {
31 INVALID_FENCE,
32 NULL_FENCE,
33 SURFACE_FENCE,
34 SYNC_FENCE,
35 };
36
Sungtak Leefce527c2021-03-20 01:24:41 -070037 virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;
38
39 virtual bool valid() const = 0;
40
41 virtual bool ready() const = 0;
42
43 virtual int fd() const = 0;
44
45 virtual bool isHW() const = 0;
46
Lubin Yin92427a52022-04-18 16:57:39 -070047 virtual type_t type() const = 0;
48
49 /**
50 * Create a native handle for the fence so it can be marshalled.
51 * The native handle must store fence type in the first integer.
52 *
53 * \return a valid native handle if the fence can be marshalled, otherwise return null.
54 */
55 virtual native_handle_t *createNativeHandle() const = 0;
56
Sungtak Leefce527c2021-03-20 01:24:41 -070057 virtual ~Impl() = default;
58
59 Impl() = default;
Lubin Yin92427a52022-04-18 16:57:39 -070060
61 static type_t GetTypeFromNativeHandle(const native_handle_t* nh) {
62 if (nh && nh->numFds >= 0 && nh->numFds <= MAX_FENCE_FDS && nh->numInts > 0) {
63 return static_cast<type_t>(nh->data[nh->numFds]);
64 }
65 return INVALID_FENCE;
66 }
Sungtak Leefce527c2021-03-20 01:24:41 -070067};
68
69c2_status_t C2Fence::wait(c2_nsecs_t timeoutNs) {
70 if (mImpl) {
71 return mImpl->wait(timeoutNs);
72 }
73 // null fence is always signalled.
74 return C2_OK;
75}
76
77bool C2Fence::valid() const {
78 if (mImpl) {
79 return mImpl->valid();
80 }
81 // null fence is always valid.
82 return true;
83}
84
85bool C2Fence::ready() const {
86 if (mImpl) {
87 return mImpl->ready();
88 }
89 // null fence is always signalled.
90 return true;
91}
92
93int C2Fence::fd() const {
94 if (mImpl) {
95 return mImpl->fd();
96 }
97 // null fence does not have fd.
98 return -1;
99}
100
101bool C2Fence::isHW() const {
102 if (mImpl) {
103 return mImpl->isHW();
104 }
105 return false;
106}
107
108/**
109 * Fence implementation for C2BufferQueueBlockPool based block allocation.
110 * The implementation supports all C2Fence interface except fd().
111 */
112class _C2FenceFactory::SurfaceFenceImpl: public C2Fence::Impl {
113public:
114 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
115 if (mPtr) {
116 return mPtr->waitForChange(mWaitId, timeoutNs);
117 }
118 return C2_OK;
119 }
120
121 virtual bool valid() const {
122 return mPtr;
123 }
124
125 virtual bool ready() const {
126 uint32_t status;
127 if (mPtr) {
128 mPtr->lock();
129 status = mPtr->getWaitIdLocked();
130 mPtr->unlock();
131
132 return status != mWaitId;
133 }
134 return true;
135 }
136
137 virtual int fd() const {
138 // does not support fd, since this is shared mem and futex based
139 return -1;
140 }
141
142 virtual bool isHW() const {
143 return false;
144 }
145
Lubin Yin92427a52022-04-18 16:57:39 -0700146 virtual type_t type() const {
147 return SURFACE_FENCE;
148 }
149
150 virtual native_handle_t *createNativeHandle() const {
Lajos Molnara272dd72022-05-25 11:05:08 -0700151 ALOGD("Cannot create native handle from surface fence");
Lubin Yin92427a52022-04-18 16:57:39 -0700152 return nullptr;
153 }
154
Sungtak Leefce527c2021-03-20 01:24:41 -0700155 virtual ~SurfaceFenceImpl() {};
156
157 SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
158 mSyncMem(syncMem),
159 mPtr(syncMem ? syncMem->mem() : nullptr),
160 mWaitId(syncMem ? waitId : 0) {}
161private:
162 const std::shared_ptr<const C2SurfaceSyncMemory> mSyncMem; // This is for life-cycle guarantee
163 C2SyncVariables *const mPtr;
164 const uint32_t mWaitId;
165};
166
167C2Fence::C2Fence(std::shared_ptr<Impl> impl) : mImpl(impl) {}
168
169C2Fence _C2FenceFactory::CreateSurfaceFence(
170 std::shared_ptr<C2SurfaceSyncMemory> syncMem,
171 uint32_t waitId) {
172 if (syncMem) {
173 C2Fence::Impl *p
174 = new _C2FenceFactory::SurfaceFenceImpl(syncMem, waitId);
175 if (p->valid()) {
176 return C2Fence(std::shared_ptr<C2Fence::Impl>(p));
177 } else {
178 delete p;
179 }
180 }
181 return C2Fence();
182}
Lubin Yin92427a52022-04-18 16:57:39 -0700183
184using namespace android;
185
186class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
187public:
188 virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
Lubin Yin164f9f82022-06-14 16:10:10 -0700189 int64_t timeoutMs = timeoutNs / 1000000;
Lubin Yin92427a52022-04-18 16:57:39 -0700190 if (timeoutMs > INT_MAX) {
191 timeoutMs = INT_MAX;
192 }
Lubin Yin92427a52022-04-18 16:57:39 -0700193 switch (mFence->wait((int)timeoutMs)) {
194 case NO_ERROR:
195 return C2_OK;
196 case -ETIME:
197 return C2_TIMED_OUT;
198 default:
199 return C2_CORRUPTED;
200 }
201 }
202
203 virtual bool valid() const {
Uma Mehta1ac98782022-09-28 16:47:35 +0530204 return (mFence && (mFence->getStatus() != Fence::Status::Invalid));
Lubin Yin92427a52022-04-18 16:57:39 -0700205 }
206
207 virtual bool ready() const {
208 return mFence->getStatus() == Fence::Status::Signaled;
209 }
210
211 virtual int fd() const {
212 return mFence->dup();
213 }
214
Uma Mehta1ac98782022-09-28 16:47:35 +0530215 std::vector<int> fds() const {
216 std::vector<int> retFds;
217 for (int index = 0; index < mListFences.size(); index++) {
218 retFds.push_back(mListFences[index]->dup());
219 }
220 return retFds;
221 }
222
Lubin Yin92427a52022-04-18 16:57:39 -0700223 virtual bool isHW() const {
224 return true;
225 }
226
227 virtual type_t type() const {
228 return SYNC_FENCE;
229 }
230
231 virtual native_handle_t *createNativeHandle() const {
Uma Mehta1ac98782022-09-28 16:47:35 +0530232 std::vector<int> nativeFds = fds();
233 nativeFds.push_back(fd());
234 native_handle_t* nh = native_handle_create(nativeFds.size(), 1);
Lubin Yin92427a52022-04-18 16:57:39 -0700235 if (!nh) {
236 ALOGE("Failed to allocate native handle for sync fence");
Uma Mehta1ac98782022-09-28 16:47:35 +0530237 for (int fd : nativeFds) {
238 close(fd);
239 }
Lubin Yin92427a52022-04-18 16:57:39 -0700240 return nullptr;
241 }
Uma Mehta1ac98782022-09-28 16:47:35 +0530242
243 for (int i = 0; i < nativeFds.size(); i++) {
244 nh->data[i] = nativeFds[i];
245 }
246 nh->data[nativeFds.size()] = type();
Lubin Yin92427a52022-04-18 16:57:39 -0700247 return nh;
248 }
249
250 virtual ~SyncFenceImpl() {};
251
252 SyncFenceImpl(int fenceFd) :
Uma Mehta1ac98782022-09-28 16:47:35 +0530253 mFence(sp<Fence>::make(fenceFd)) {
254 mListFences.clear();
255 if (mFence) {
256 mListFences.push_back(mFence);
257 }
258 }
259
260 SyncFenceImpl(const std::vector<int>& fenceFds, int mergedFd) {
261 mListFences.clear();
262
263 for (int fenceFd : fenceFds) {
264 if (fenceFd < 0) {
265 continue;
266 } else {
267 mListFences.push_back(sp<Fence>::make(fenceFd));
268 if (!mListFences.back()) {
269 mFence.clear();
270 break;
271 }
272 if (mergedFd == -1) {
273 mFence = (mFence == nullptr) ? (mListFences.back()) :
274 (Fence::merge("syncFence", mFence, mListFences.back()));
275 }
276 }
277 }
278 if (mergedFd != -1)
279 {
280 mFence = sp<Fence>::make(mergedFd);
281 }
282 if (!mFence) {
283 mListFences.clear();
284 }
285 }
Lubin Yin92427a52022-04-18 16:57:39 -0700286
287 static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(const native_handle_t* nh) {
Uma Mehta1ac98782022-09-28 16:47:35 +0530288 if (!nh || nh->numFds < 1 || nh->numInts < 1) {
Lubin Yin92427a52022-04-18 16:57:39 -0700289 ALOGE("Invalid handle for sync fence");
290 return nullptr;
291 }
Uma Mehta1ac98782022-09-28 16:47:35 +0530292 std::vector<int> fds;
293 for (int i = 0; i < nh->numFds-1; i++) {
294 fds.push_back(dup(nh->data[i]));
295 }
296 std::shared_ptr<SyncFenceImpl> p = (nh->numFds == 1)?
297 (std::make_shared<SyncFenceImpl>(fds.back())):
298 (std::make_shared<SyncFenceImpl>(fds, (dup(nh->data[nh->numFds-1]))));
Lubin Yin92427a52022-04-18 16:57:39 -0700299 if (!p) {
300 ALOGE("Failed to allocate sync fence impl");
Uma Mehta1ac98782022-09-28 16:47:35 +0530301 for (int fd : fds) {
302 close(fd);
303 }
Lubin Yin92427a52022-04-18 16:57:39 -0700304 }
305 return p;
306 }
307
308private:
Uma Mehta1ac98782022-09-28 16:47:35 +0530309 std::vector<sp<Fence>> mListFences;
310 sp<Fence> mFence; //merged fence in case mListFences size > 0
Lubin Yin92427a52022-04-18 16:57:39 -0700311};
312
Uma Mehta1ac98782022-09-28 16:47:35 +0530313std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence) {
314 std::vector<int> retFds;
315 if ((fence.mImpl) && (fence.mImpl->type() == C2Fence::Impl::SYNC_FENCE)) {
316 retFds = static_cast<_C2FenceFactory::SyncFenceImpl *>(fence.mImpl.get())->fds();
317 }
318 return retFds;
319}
320
Lubin Yin92427a52022-04-18 16:57:39 -0700321C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) {
322 std::shared_ptr<C2Fence::Impl> p;
323 if (fenceFd >= 0) {
324 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFd);
325 if (!p) {
326 ALOGE("Failed to allocate sync fence impl");
327 close(fenceFd);
Uma Mehta1ac98782022-09-28 16:47:35 +0530328 } else if (!p->valid()) {
Lubin Yin92427a52022-04-18 16:57:39 -0700329 p.reset();
330 }
331 } else {
332 ALOGE("Create sync fence from invalid fd");
333 }
334 return C2Fence(p);
335}
336
Uma Mehta1ac98782022-09-28 16:47:35 +0530337C2Fence _C2FenceFactory::CreateMultipleFdSyncFence(const std::vector<int>& fenceFds) {
338 std::shared_ptr<C2Fence::Impl> p;
339 if (fenceFds.size() > 0) {
340 p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFds, -1);
341 if (!p) {
342 ALOGE("Failed to allocate sync fence impl closing FDs");
343 for (int fenceFd : fenceFds) {
344 close(fenceFd);
345 }
346 } else if (!p->valid()) {
347 ALOGE("Invalid sync fence created");
348 p.reset();
349 }
350 } else {
351 ALOGE("Create sync fence from invalid fd list of size 0");
352 }
353 return C2Fence(p);
354}
355
Lubin Yin92427a52022-04-18 16:57:39 -0700356native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
357 return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
358}
359
360C2Fence _C2FenceFactory::CreateFromNativeHandle(const native_handle_t* handle) {
361 if (!handle) {
362 return C2Fence();
363 }
364 C2Fence::Impl::type_t type = C2Fence::Impl::GetTypeFromNativeHandle(handle);
365 std::shared_ptr<C2Fence::Impl> p;
366 switch (type) {
367 case C2Fence::Impl::SYNC_FENCE:
368 p = SyncFenceImpl::CreateFromNativeHandle(handle);
369 break;
370 default:
Lajos Molnara272dd72022-05-25 11:05:08 -0700371 ALOGD("Unsupported fence type %d", type);
372 // return a null-fence in this case
Lubin Yin92427a52022-04-18 16:57:39 -0700373 break;
374 }
375 if (p && !p->valid()) {
376 p.reset();
377 }
378 return C2Fence(p);
379}
380