• 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 
C2SyncVariablesC2SyncVariables115     C2SyncVariables() {}
116 
117 private:
118     /**
119      * signal one waiter to wake up.
120      */
121     int signal();
122 
123     /**
124      * signal all waiter to wake up.
125      */
126     int broadcast();
127 
128     /**
129      * wait for signal or broadcast.
130      */
131     int wait();
132 
133     std::atomic<uint32_t> mLock;
134     std::atomic<uint32_t> mCond;
135     int32_t mMaxDequeueCount;
136     int32_t mCurDequeueCount;
137     SyncStatus mStatus;
138 };
139 
140 /**
141  * Shared memory in order to synchronize information for Surface(IGBP)
142  * based output buffer allocation.
143  */
144 class C2SurfaceSyncMemory {
145 public:
146     /**
147      * Shared memory handle in order to synchronize information for
148      * Surface based output buffer allocation.
149      */
150     struct HandleSyncMem : public native_handle_t {
HandleSyncMemHandleSyncMem151         HandleSyncMem(int fd, size_t size) :
152             native_handle_t(cHeader),
153             mFds{fd},
154             mInts{int(size & 0xFFFFFFFF),
155                 int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic} {}
156 
157         /** Returns a file descriptor of the shared memory
158          * \return a file descriptor representing the shared memory
159          */
memFdHandleSyncMem160         int memFd() const {return mFds.mMem;}
161 
162         /** Returns the size of the shared memory */
sizeHandleSyncMem163         size_t size() const {
164             return size_t(unsigned(mInts.mSizeLo))
165                     | size_t(uint64_t(unsigned(mInts.mSizeHi)) << 32);
166         }
167 
168         /** Check whether the native handle is in the form of HandleSyncMem
169          *
170          * \return whether the native handle is compatible
171          */
172         static bool isValid(const native_handle_t * const o);
173 
174     protected:
175         struct {
176             int mMem;
177         } mFds;
178         struct {
179             int mSizeLo;
180             int mSizeHi;
181             int mMagic;
182         } mInts;
183     private:
184         enum {
185             kMagic = 'ssm\x00',
186             numFds = sizeof(mFds) / sizeof(int),
187             numInts = sizeof(mInts) / sizeof(int),
188             version = sizeof(native_handle_t)
189         };
190         const static native_handle_t cHeader;
191     };
192 
193     /**
194      * Imports a shared memory object from a native handle(The shared memory is already existing).
195      * This is usually used after native_handle_t is passed via RPC.
196      *
197      * \param handle        handle representing shared memory for output buffer allocation.
198      */
199     static std::shared_ptr<C2SurfaceSyncMemory> Import(native_handle_t *handle);
200 
201     /**
202      * Creats a shared memory object for synchronization of output buffer allocation.
203      * Shared memory creation should be done explicitly.
204      *
205      * \param fd            file descriptor to shared memory
206      * \param size          size of the shared memory
207      */
208     static std::shared_ptr<C2SurfaceSyncMemory> Create(int fd, size_t size);
209 
210     /**
211      * Returns a handle representing the shread memory for synchronization of
212      * output buffer allocation.
213      */
214     native_handle_t *handle();
215 
216     /**
217      * Returns synchronization object which will provide synchronization primitives.
218      *
219      * \return a ptr to synchronization primitive class
220      */
221     C2SyncVariables *mem();
222 
223     ~C2SurfaceSyncMemory();
224 
225 private:
226     bool mInit;
227     HandleSyncMem *mHandle;
228     C2SyncVariables *mMem;
229 
230     C2SurfaceSyncMemory();
231 };
232 
233 #endif // STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_
234