• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
19 #include <cutils/native_handle.h>
20 #include <utils/Log.h>
21 #include <ui/Fence.h>
22 
23 #include <C2FenceFactory.h>
24 #include <C2SurfaceSyncObj.h>
25 
26 #define MAX_FENCE_FDS 1
27 
28 class C2Fence::Impl {
29 public:
30     enum type_t : uint32_t {
31         INVALID_FENCE,
32         NULL_FENCE,
33         SURFACE_FENCE,
34         SYNC_FENCE,
35     };
36 
37     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 
47     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 
57     virtual ~Impl() = default;
58 
59     Impl() = default;
60 
GetTypeFromNativeHandle(const native_handle_t * nh)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     }
67 };
68 
wait(c2_nsecs_t timeoutNs)69 c2_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 
valid() const77 bool C2Fence::valid() const {
78     if (mImpl) {
79         return mImpl->valid();
80     }
81     // null fence is always valid.
82     return true;
83 }
84 
ready() const85 bool C2Fence::ready() const {
86     if (mImpl) {
87         return mImpl->ready();
88     }
89     // null fence is always signalled.
90     return true;
91 }
92 
fd() const93 int C2Fence::fd() const {
94     if (mImpl) {
95         return mImpl->fd();
96     }
97     // null fence does not have fd.
98     return -1;
99 }
100 
isHW() const101 bool 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  */
112 class _C2FenceFactory::SurfaceFenceImpl: public C2Fence::Impl {
113 public:
wait(c2_nsecs_t timeoutNs)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 
valid() const121     virtual bool valid() const {
122         return mPtr;
123     }
124 
ready() const125     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 
fd() const137     virtual int fd() const {
138         // does not support fd, since this is shared mem and futex based
139         return -1;
140     }
141 
isHW() const142     virtual bool isHW() const {
143         return false;
144     }
145 
type() const146     virtual type_t type() const {
147         return SURFACE_FENCE;
148     }
149 
createNativeHandle() const150     virtual native_handle_t *createNativeHandle() const {
151         ALOGD("Cannot create native handle from surface fence");
152         return nullptr;
153     }
154 
~SurfaceFenceImpl()155     virtual ~SurfaceFenceImpl() {};
156 
SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t waitId)157     SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
158             mSyncMem(syncMem),
159             mPtr(syncMem ? syncMem->mem() : nullptr),
160             mWaitId(syncMem ? waitId : 0) {}
161 private:
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 
C2Fence(std::shared_ptr<Impl> impl)167 C2Fence::C2Fence(std::shared_ptr<Impl> impl) : mImpl(impl) {}
168 
CreateSurfaceFence(std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t waitId)169 C2Fence _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 }
183 
184 using namespace android;
185 
186 class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
187 public:
wait(c2_nsecs_t timeoutNs)188     virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
189         int64_t timeoutMs = timeoutNs / 1000000;
190         if (timeoutMs > INT_MAX) {
191             timeoutMs = INT_MAX;
192         }
193 
194         switch (mFence->wait((int)timeoutMs)) {
195             case NO_ERROR:
196                 return C2_OK;
197             case -ETIME:
198                 return C2_TIMED_OUT;
199             default:
200                 return C2_CORRUPTED;
201         }
202     }
203 
valid() const204     virtual bool valid() const {
205         return mFence->getStatus() != Fence::Status::Invalid;
206     }
207 
ready() const208     virtual bool ready() const {
209         return mFence->getStatus() == Fence::Status::Signaled;
210     }
211 
fd() const212     virtual int fd() const {
213         return mFence->dup();
214     }
215 
isHW() const216     virtual bool isHW() const {
217         return true;
218     }
219 
type() const220     virtual type_t type() const {
221         return SYNC_FENCE;
222     }
223 
createNativeHandle() const224     virtual native_handle_t *createNativeHandle() const {
225         native_handle_t* nh = native_handle_create(1, 1);
226         if (!nh) {
227             ALOGE("Failed to allocate native handle for sync fence");
228             return nullptr;
229         }
230         nh->data[0] = fd();
231         nh->data[1] = type();
232         return nh;
233     }
234 
~SyncFenceImpl()235     virtual ~SyncFenceImpl() {};
236 
SyncFenceImpl(int fenceFd)237     SyncFenceImpl(int fenceFd) :
238             mFence(sp<Fence>::make(fenceFd)) {}
239 
CreateFromNativeHandle(const native_handle_t * nh)240     static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(const native_handle_t* nh) {
241         if (!nh || nh->numFds != 1 || nh->numInts != 1) {
242             ALOGE("Invalid handle for sync fence");
243             return nullptr;
244         }
245         int fd = dup(nh->data[0]);
246         std::shared_ptr<SyncFenceImpl> p = std::make_shared<SyncFenceImpl>(fd);
247         if (!p) {
248             ALOGE("Failed to allocate sync fence impl");
249             close(fd);
250         }
251         return p;
252     }
253 
254 private:
255     const sp<Fence> mFence;
256 };
257 
CreateSyncFence(int fenceFd)258 C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) {
259     std::shared_ptr<C2Fence::Impl> p;
260     if (fenceFd >= 0) {
261         p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFd);
262         if (!p) {
263             ALOGE("Failed to allocate sync fence impl");
264             close(fenceFd);
265         }
266         if (!p->valid()) {
267             p.reset();
268         }
269     } else {
270         ALOGE("Create sync fence from invalid fd");
271     }
272     return C2Fence(p);
273 }
274 
CreateNativeHandle(const C2Fence & fence)275 native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
276     return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
277 }
278 
CreateFromNativeHandle(const native_handle_t * handle)279 C2Fence _C2FenceFactory::CreateFromNativeHandle(const native_handle_t* handle) {
280     if (!handle) {
281         return C2Fence();
282     }
283     C2Fence::Impl::type_t type = C2Fence::Impl::GetTypeFromNativeHandle(handle);
284     std::shared_ptr<C2Fence::Impl> p;
285     switch (type) {
286         case C2Fence::Impl::SYNC_FENCE:
287             p = SyncFenceImpl::CreateFromNativeHandle(handle);
288             break;
289         default:
290             ALOGD("Unsupported fence type %d", type);
291             // return a null-fence in this case
292             break;
293     }
294     if (p && !p->valid()) {
295         p.reset();
296     }
297     return C2Fence(p);
298 }
299 
300