blob: ac87fe4c89068237a3d44331952d8f1511500b8f [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#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 */
30struct 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 */
Sungtak Leedb14cba2021-04-10 00:50:23 -070056 void setInitialDequeueCountLocked(int32_t maxDequeueCount, int32_t curDequeueCount);
Sungtak Leefce527c2021-03-20 01:24:41 -070057
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
114 C2SyncVariables() {}
115
116private:
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 */
143class C2SurfaceSyncMemory {
144public:
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 {
150 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 */
159 int memFd() const {return mFds.mMem;}
160
161 /** Returns the size of the shared memory */
162 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
224private:
225 bool mInit;
226 HandleSyncMem *mHandle;
227 C2SyncVariables *mMem;
228
229 C2SurfaceSyncMemory();
230};
231
232#endif // STAGEFRIGHT_CODEC2_SURFACE_SYNC_OBJ_H_