2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef ANDROID_SF_SHARED_BUFFER_STACK_H
18 #define ANDROID_SF_SHARED_BUFFER_STACK_H
21 #include <sys/types.h>
23 #include <cutils/compiler.h>
25 #include <utils/Debug.h>
26 #include <utils/threads.h>
27 #include <utils/String8.h>
32 // ---------------------------------------------------------------------------
35 * These classes manage a stack of buffers in shared memory.
37 * SharedClient: represents a client with several stacks
38 * SharedBufferStack: represents a stack of buffers
39 * SharedBufferClient: manipulates the SharedBufferStack from the client side
40 * SharedBufferServer: manipulates the SharedBufferStack from the server side
42 * Buffers can be dequeued until there are none available, they can be locked
43 * unless they are in use by the server, which is only the case for the last
44 * dequeue-able buffer. When these various conditions are not met, the caller
45 * waits until the condition is met.
49 // ----------------------------------------------------------------------------
52 class SharedBufferStack;
55 // ----------------------------------------------------------------------------
57 class SharedBufferStack
59 friend class SharedClient;
60 friend class SharedBufferBase;
61 friend class SharedBufferClient;
62 friend class SharedBufferServer;
65 // When changing these values, the COMPILE_TIME_ASSERT at the end of this
66 // file need to be updated.
67 static const unsigned int NUM_LAYERS_MAX = 31;
68 static const unsigned int NUM_BUFFER_MAX = 16;
69 static const unsigned int NUM_BUFFER_MIN = 2;
70 static const unsigned int NUM_DISPLAY_MAX = 4;
72 struct Statistics { // 4 longs
73 typedef int32_t usecs_t;
82 struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
83 static const unsigned int NUM_RECT_MAX = 5;
85 SmallRect rects[NUM_RECT_MAX];
89 FlatRegion dirtyRegion;
96 void init(int32_t identity);
97 status_t setDirtyRegion(int buffer, const Region& reg);
98 status_t setCrop(int buffer, const Rect& reg);
99 status_t setTransform(int buffer, uint8_t transform);
100 Region getDirtyRegion(int buffer) const;
101 Rect getCrop(int buffer) const;
102 uint32_t getTransform(int buffer) const;
104 // these attributes are part of the conditions/updates
105 volatile int32_t head; // server's current front buffer
106 volatile int32_t available; // number of dequeue-able buffers
107 volatile int32_t queued; // number of buffers waiting for post
108 volatile int32_t reserved1;
109 volatile status_t status; // surface's status code
111 // not part of the conditions
112 volatile int32_t reallocMask;
113 volatile int8_t index[NUM_BUFFER_MAX];
115 int32_t identity; // surface's identity (const)
116 int32_t token; // surface's token (for debugging)
118 int8_t headBuf; // last retired buffer
119 uint8_t reservedBytes[3];
121 BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
124 // ----------------------------------------------------------------------------
132 status_t validate(size_t token) const;
135 friend class SharedBufferBase;
136 friend class SharedBufferClient;
137 friend class SharedBufferServer;
139 // FIXME: this should be replaced by a lock-less primitive
142 SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
145 // ============================================================================
147 class SharedBufferBase
150 SharedBufferBase(SharedClient* sharedClient, int surface,
153 status_t getStatus() const;
154 int32_t getIdentity() const;
155 String8 dump(char const* prefix) const;
158 SharedClient* const mSharedClient;
159 SharedBufferStack* const mSharedStack;
162 friend struct Update;
163 friend struct QueueUpdate;
165 struct ConditionBase {
166 SharedBufferStack& stack;
167 inline ConditionBase(SharedBufferBase* sbc)
168 : stack(*sbc->mSharedStack) { }
169 virtual ~ConditionBase() { };
170 virtual bool operator()() const = 0;
171 virtual const char* name() const = 0;
173 status_t waitForCondition(const ConditionBase& condition);
176 SharedBufferStack& stack;
177 inline UpdateBase(SharedBufferBase* sbb)
178 : stack(*sbb->mSharedStack) { }
180 template <typename T>
181 status_t updateCondition(T update);
184 template <typename T>
185 status_t SharedBufferBase::updateCondition(T update) {
186 SharedClient& client( *mSharedClient );
187 Mutex::Autolock _l(client.lock);
188 ssize_t result = update();
189 client.cv.broadcast();
193 // ----------------------------------------------------------------------------
195 class SharedBufferClient : public SharedBufferBase
198 SharedBufferClient(SharedClient* sharedClient, int surface, int num,
202 status_t undoDequeue(int buf);
204 status_t lock(int buf);
205 status_t cancel(int buf);
206 status_t queue(int buf);
207 bool needNewBuffer(int buffer) const;
208 status_t setDirtyRegion(int buffer, const Region& reg);
209 status_t setCrop(int buffer, const Rect& reg);
210 status_t setTransform(int buffer, uint32_t transform);
212 class SetBufferCountCallback {
213 friend class SharedBufferClient;
214 virtual status_t operator()(int bufferCount) const = 0;
216 virtual ~SetBufferCountCallback() { }
218 status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
221 friend struct Condition;
222 friend struct DequeueCondition;
223 friend struct LockCondition;
225 struct QueueUpdate : public UpdateBase {
226 inline QueueUpdate(SharedBufferBase* sbb);
227 inline ssize_t operator()();
230 struct DequeueUpdate : public UpdateBase {
231 inline DequeueUpdate(SharedBufferBase* sbb);
232 inline ssize_t operator()();
235 struct CancelUpdate : public UpdateBase {
237 inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
238 inline ssize_t operator()();
243 struct DequeueCondition : public ConditionBase {
244 inline DequeueCondition(SharedBufferClient* sbc);
245 inline bool operator()() const;
246 inline const char* name() const { return "DequeueCondition"; }
249 struct LockCondition : public ConditionBase {
251 inline LockCondition(SharedBufferClient* sbc, int buf);
252 inline bool operator()() const;
253 inline const char* name() const { return "LockCondition"; }
256 int32_t computeTail() const;
258 mutable RWLock mLock;
264 nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
267 // ----------------------------------------------------------------------------
269 class SharedBufferServer
270 : public SharedBufferBase,
271 public LightRefBase<SharedBufferServer>
274 SharedBufferServer(SharedClient* sharedClient, int surface, int num,
277 ssize_t retireAndLock();
278 void setStatus(status_t status);
279 status_t reallocateAll();
280 status_t reallocateAllExcept(int buffer);
281 int32_t getQueuedCount() const;
282 Region getDirtyRegion(int buffer) const;
283 Rect getCrop(int buffer) const;
284 uint32_t getTransform(int buffer) const;
286 status_t resize(int newNumBuffers);
288 SharedBufferStack::Statistics getStats() const;
292 friend class LightRefBase<SharedBufferServer>;
293 ~SharedBufferServer();
296 * BufferList is basically a fixed-capacity sorted-vector of
297 * unsigned 5-bits ints using a 32-bits int as storage.
298 * it has efficient iterators to find items in the list and not in the list.
304 BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
305 : mCapacity(c), mList(0) { }
306 status_t add(int value);
307 status_t remove(int value);
308 uint32_t getMask() const { return mList; }
310 class const_iterator {
311 friend class BufferList;
313 const_iterator(uint32_t mask) :
314 mask(mask), curr(__builtin_clz(mask)) {
317 inline bool operator == (const const_iterator& rhs) const {
318 return mask == rhs.mask;
320 inline bool operator != (const const_iterator& rhs) const {
321 return mask != rhs.mask;
323 inline int operator *() const { return curr; }
324 inline const const_iterator& operator ++() {
325 mask &= ~(1<<(31-curr));
326 curr = __builtin_clz(mask);
331 inline const_iterator begin() const {
332 return const_iterator(mList);
334 inline const_iterator end() const {
335 return const_iterator(0);
337 inline const_iterator free_begin() const {
338 uint32_t mask = (1 << (32-mCapacity)) - 1;
339 return const_iterator( ~(mList | mask) );
343 // this protects mNumBuffers and mBufferList
344 mutable RWLock mLock;
346 BufferList mBufferList;
349 struct RetireUpdate : public UpdateBase {
350 const int numBuffers;
351 inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
352 inline ssize_t operator()();
355 struct StatusUpdate : public UpdateBase {
356 const status_t status;
357 inline StatusUpdate(SharedBufferBase* sbb, status_t status);
358 inline ssize_t operator()();
362 // ===========================================================================
364 struct display_cblk_t
378 struct surface_flinger_cblk_t // 4KB max
383 display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
386 // ---------------------------------------------------------------------------
388 COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768)
389 COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
391 // ---------------------------------------------------------------------------
392 }; // namespace android
394 #endif /* ANDROID_SF_SHARED_BUFFER_STACK_H */