• 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 #ifndef STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_
18 #define STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_
19 
20 #include <cutils/native_handle.h>
21 #include <memory>
22 #include <atomic>
23 
24 #include <C2Buffer.h>
25 
26 /**
27  * Futex based lock / wait implementation for sharing output buffer allocation
28  * information between Framework and HAL.
29  */
30 struct C2SyncVariables {
31     enum SyncStatus : uint32_t {
32            STATUS_INIT = 0,         // When surface configuration starts.
33            STATUS_ACTIVE = 1,       // When surface configuration finishs.
34                                     // STATUS_INIT -> STATUS_ACTIVE
35            STATUS_SWITCHING = 2,    // When the surface is replaced by a new surface
36                                     // during surface configuration.
37                                     // STATUS_ACTIVE -> STATUS_SWITCHING
38     };
39 
40     /**
41      * Lock the memory region
42      */
43     int lock();
44 
45     /**
46      * Unlock the memory region
47      */
48     int unlock();
49 
50     /**
51      * Set initial dequeued buffer count.
52      *
53      * \param maxDequeueCount           Initial value of # of max dequeued buffer count
54      * \param curDequeueCount           Initial value of # of current dequeued buffer count
55      */
56     void setInitialDequeueCountLocked(int32_t maxDequeueCount, int32_t curDequeueCount);
57 
58     /**
59      * Get a waitId which will be used to implement fence.
60      */
61     uint32_t getWaitIdLocked();
62 
63     /**
64      * Return whether the upcoming dequeue operation is not blocked.
65      * if it's blocked and waitId is non-null, waitId is returned to be used for waiting.
66      *
67      * \retval false    dequeue operation is blocked now.
68      * \retval true     dequeue operation is possible.
69      */
70     bool isDequeueableLocked(uint32_t *waitId = nullptr);
71 
72     /**
73      * Notify a buffer is queued. Return whether the upcoming dequeue operation
74      * is not blocked. if it's blocked and waitId is non-null, waitId is returned
75      * to be used for waiting. Notify(wake-up) waitors only when 'notify' is
76      * true.
77      *
78      * \retval false    dequeue operation is blocked now.
79      * \retval true     dequeue operation is possible.
80      */
81     bool notifyQueuedLocked(uint32_t *waitId = nullptr, bool notify = true);
82 
83     /**
84      * Notify a buffer is dequeued.
85      */
86     void notifyDequeuedLocked();
87 
88     /**
89      * Set sync status.
90      */
91     void setSyncStatusLocked(SyncStatus status);
92 
93     /**
94      * Get sync status.
95      */
96     C2SyncVariables::SyncStatus getSyncStatusLocked();
97 
98     /**
99      * Update current max dequeue count.
100      */
101     void updateMaxDequeueCountLocked(int32_t maxDequeueCount);
102 
103     /**
104      * Wait until status is no longer equal to waitId, or until timeout.
105      *
106      * \param waitId            internal status for waiting until it is changed.
107      * \param timeousNs         nano seconds to timeout.
108      *
109      * \retval C2_TIMEDOUT      change does not happen during waiting.
110      * \retval C2_BAD_VALUE     invalid event waiting.
111      * \retval C2_OK            change was signalled.
112      */
113     c2_status_t waitForChange(uint32_t waitId, c2_nsecs_t timeoutNs);
114 
115     /**
116      * Wake up and expire all waitors.
117      */
118     void notifyAll();
119 
C2SyncVariablesC2SyncVariables120     C2SyncVariables() {}
121 
122 private:
123     /**
124      * signal one waiter to wake up.
125      */
126     int signal();
127 
128     /**
129      * signal all waiter to wake up.
130      */
131     int broadcast();
132 
133     /**
134      * wait for signal or broadcast.
135      */
136     int wait();
137 
138     std::atomic<uint32_t> mLock;
139     std::atomic<uint32_t> mCond;
140     int32_t mMaxDequeueCount;
141     int32_t mCurDequeueCount;
142     SyncStatus mStatus;
143 };
144 
145 /**
146  * Shared memory in order to synchronize information for Surface(IGBP)
147  * based output buffer allocation.
148  */
149 class C2SurfaceSyncMemory {
150 public:
151     /**
152      * Shared memory handle in order to synchronize information for
153      * Surface based output buffer allocation.
154      */
155     struct HandleSyncMem : public native_handle_t {
HandleSyncMemHandleSyncMem156         HandleSyncMem(int fd, size_t size) :
157             native_handle_t(cHeader),
158             mFds{fd},
159             mInts{int(size & 0xFFFFFFFF),
160                 int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic} {}
161 
162         /** Returns a file descriptor of the shared memory
163          * \return a file descriptor representing the shared memory
164          */
memFdHandleSyncMem165         int memFd() const {return mFds.mMem;}
166 
167         /** Returns the size of the shared memory */
sizeHandleSyncMem168         size_t size() const {
169             return size_t(unsigned(mInts.mSizeLo))
170                     | size_t(uint64_t(unsigned(mInts.mSizeHi)) << 32);
171         }
172 
173         /** Check whether the native handle is in the form of HandleSyncMem
174          *
175          * \return whether the native handle is compatible
176          */
177         static bool isValid(const native_handle_t * const o);
178 
179     protected:
180         struct {
181             int mMem;
182         } mFds;
183         struct {
184             int mSizeLo;
185             int mSizeHi;
186             int mMagic;
187         } mInts;
188     private:
189         enum {
190             kMagic = 'ssm\x00',
191             numFds = sizeof(mFds) / sizeof(int),
192             numInts = sizeof(mInts) / sizeof(int),
193             version = sizeof(native_handle_t)
194         };
195         const static native_handle_t cHeader;
196     };
197 
198     /**
199      * Imports a shared memory object from a native handle(The shared memory is already existing).
200      * This is usually used after native_handle_t is passed via RPC.
201      *
202      * \param handle        handle representing shared memory for output buffer allocation.
203      */
204     static std::shared_ptr<C2SurfaceSyncMemory> Import(native_handle_t *handle);
205 
206     /**
207      * Creats a shared memory object for synchronization of output buffer allocation.
208      * Shared memory creation should be done explicitly.
209      *
210      * \param fd            file descriptor to shared memory
211      * \param size          size of the shared memory
212      */
213     static std::shared_ptr<C2SurfaceSyncMemory> Create(int fd, size_t size);
214 
215     /**
216      * Returns a handle representing the shread memory for synchronization of
217      * output buffer allocation.
218      */
219     native_handle_t *handle();
220 
221     /**
222      * Returns synchronization object which will provide synchronization primitives.
223      *
224      * \return a ptr to synchronization primitive class
225      */
226     C2SyncVariables *mem();
227 
228     ~C2SurfaceSyncMemory();
229 
230 private:
231     bool mInit;
232     HandleSyncMem *mHandle;
233     C2SyncVariables *mMem;
234 
235     C2SurfaceSyncMemory();
236 };
237 
238 #endif // STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_
239