• 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.
76      *
77      * \retval false    dequeue operation is blocked now.
78      * \retval true     dequeue operation is possible.
79      */
80     bool notifyQueuedLocked(uint32_t *waitId = nullptr);
81 
82     /**
83      * Notify a buffer is dequeued.
84      */
85     void notifyDequeuedLocked();
86 
87     /**
88      * Set sync status.
89      */
90     void setSyncStatusLocked(SyncStatus status);
91 
92     /**
93      * Get sync status.
94      */
95     C2SyncVariables::SyncStatus getSyncStatusLocked();
96 
97     /**
98      * Update current max dequeue count.
99      */
100     void updateMaxDequeueCountLocked(int32_t maxDequeueCount);
101 
102     /**
103      * Wait until status is no longer equal to waitId, or until timeout.
104      *
105      * \param waitId            internal status for waiting until it is changed.
106      * \param timeousNs         nano seconds to timeout.
107      *
108      * \retval C2_TIMEDOUT      change does not happen during waiting.
109      * \retval C2_BAD_VALUE     invalid event waiting.
110      * \retval C2_OK            change was signalled.
111      */
112     c2_status_t waitForChange(uint32_t waitId, c2_nsecs_t timeoutNs);
113 
C2SyncVariablesC2SyncVariables114     C2SyncVariables() {}
115 
116 private:
117     /**
118      * signal one waiter to wake up.
119      */
120     int signal();
121 
122     /**
123      * signal all waiter to wake up.
124      */
125     int broadcast();
126 
127     /**
128      * wait for signal or broadcast.
129      */
130     int wait();
131 
132     std::atomic<uint32_t> mLock;
133     std::atomic<uint32_t> mCond;
134     int32_t mMaxDequeueCount;
135     int32_t mCurDequeueCount;
136     SyncStatus mStatus;
137 };
138 
139 /**
140  * Shared memory in order to synchronize information for Surface(IGBP)
141  * based output buffer allocation.
142  */
143 class C2SurfaceSyncMemory {
144 public:
145     /**
146      * Shared memory handle in order to synchronize information for
147      * Surface based output buffer allocation.
148      */
149     struct HandleSyncMem : public native_handle_t {
HandleSyncMemHandleSyncMem150         HandleSyncMem(int fd, size_t size) :
151             native_handle_t(cHeader),
152             mFds{fd},
153             mInts{int(size & 0xFFFFFFFF),
154                 int((uint64_t(size) >> 32) & 0xFFFFFFFF), kMagic} {}
155 
156         /** Returns a file descriptor of the shared memory
157          * \return a file descriptor representing the shared memory
158          */
memFdHandleSyncMem159         int memFd() const {return mFds.mMem;}
160 
161         /** Returns the size of the shared memory */
sizeHandleSyncMem162         size_t size() const {
163             return size_t(unsigned(mInts.mSizeLo))
164                     | size_t(uint64_t(unsigned(mInts.mSizeHi)) << 32);
165         }
166 
167         /** Check whether the native handle is in the form of HandleSyncMem
168          *
169          * \return whether the native handle is compatible
170          */
171         static bool isValid(const native_handle_t * const o);
172 
173     protected:
174         struct {
175             int mMem;
176         } mFds;
177         struct {
178             int mSizeLo;
179             int mSizeHi;
180             int mMagic;
181         } mInts;
182     private:
183         enum {
184             kMagic = 'ssm\x00',
185             numFds = sizeof(mFds) / sizeof(int),
186             numInts = sizeof(mInts) / sizeof(int),
187             version = sizeof(native_handle_t)
188         };
189         const static native_handle_t cHeader;
190     };
191 
192     /**
193      * Imports a shared memory object from a native handle(The shared memory is already existing).
194      * This is usually used after native_handle_t is passed via RPC.
195      *
196      * \param handle        handle representing shared memory for output buffer allocation.
197      */
198     static std::shared_ptr<C2SurfaceSyncMemory> Import(native_handle_t *handle);
199 
200     /**
201      * Creats a shared memory object for synchronization of output buffer allocation.
202      * Shared memory creation should be done explicitly.
203      *
204      * \param fd            file descriptor to shared memory
205      * \param size          size of the shared memory
206      */
207     static std::shared_ptr<C2SurfaceSyncMemory> Create(int fd, size_t size);
208 
209     /**
210      * Returns a handle representing the shread memory for synchronization of
211      * output buffer allocation.
212      */
213     native_handle_t *handle();
214 
215     /**
216      * Returns synchronization object which will provide synchronization primitives.
217      *
218      * \return a ptr to synchronization primitive class
219      */
220     C2SyncVariables *mem();
221 
222     ~C2SurfaceSyncMemory();
223 
224 private:
225     bool mInit;
226     HandleSyncMem *mHandle;
227     C2SyncVariables *mMem;
228 
229     C2SurfaceSyncMemory();
230 };
231 
232 #endif // STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_
233