1 /* 2 * Copyright (C) 2007 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 ANDROID_SF_SHARED_BUFFER_STACK_H 18 #define ANDROID_SF_SHARED_BUFFER_STACK_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <cutils/compiler.h> 24 25 #include <utils/Debug.h> 26 #include <utils/threads.h> 27 #include <utils/String8.h> 28 29 #include <ui/Rect.h> 30 31 namespace android { 32 // --------------------------------------------------------------------------- 33 34 /* 35 * These classes manage a stack of buffers in shared memory. 36 * 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 41 * 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. 46 * 47 */ 48 49 // ---------------------------------------------------------------------------- 50 51 class Region; 52 class SharedBufferStack; 53 class SharedClient; 54 55 // ---------------------------------------------------------------------------- 56 57 class SharedBufferStack 58 { 59 friend class SharedClient; 60 friend class SharedBufferBase; 61 friend class SharedBufferClient; 62 friend class SharedBufferServer; 63 64 public: 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; 71 72 struct Statistics { // 4 longs 73 typedef int32_t usecs_t; 74 usecs_t totalTime; 75 usecs_t reserved[3]; 76 }; 77 78 struct SmallRect { 79 uint16_t l, t, r, b; 80 }; 81 82 struct FlatRegion { // 52 bytes = 4 * (1 + 2*N) 83 static const unsigned int NUM_RECT_MAX = 5; 84 uint32_t count; 85 SmallRect rects[NUM_RECT_MAX]; 86 }; 87 88 struct BufferData { 89 FlatRegion dirtyRegion; 90 SmallRect crop; 91 uint8_t transform; 92 uint8_t reserved[3]; 93 }; 94 95 SharedBufferStack(); 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; 103 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 inUse; // buffer currently in use by SF 109 volatile status_t status; // surface's status code 110 111 // not part of the conditions 112 volatile int32_t reallocMask; 113 volatile int8_t index[NUM_BUFFER_MAX]; 114 115 int32_t identity; // surface's identity (const) 116 int32_t token; // surface's token (for debugging) 117 Statistics stats; 118 int8_t headBuf; // last retired buffer 119 uint8_t reservedBytes[3]; 120 int32_t reserved; 121 BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes 122 }; 123 124 // ---------------------------------------------------------------------------- 125 126 // 32 KB max 127 class SharedClient 128 { 129 public: 130 SharedClient(); 131 ~SharedClient(); 132 status_t validate(size_t token) const; 133 134 private: 135 friend class SharedBufferBase; 136 friend class SharedBufferClient; 137 friend class SharedBufferServer; 138 139 // FIXME: this should be replaced by a lock-less primitive 140 Mutex lock; 141 Condition cv; 142 SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ]; 143 }; 144 145 // ============================================================================ 146 147 class SharedBufferBase 148 { 149 public: 150 SharedBufferBase(SharedClient* sharedClient, int surface, 151 int32_t identity); 152 ~SharedBufferBase(); 153 status_t getStatus() const; 154 int32_t getIdentity() const; 155 String8 dump(char const* prefix) const; 156 157 protected: 158 SharedClient* const mSharedClient; 159 SharedBufferStack* const mSharedStack; 160 const int mIdentity; 161 162 friend struct Update; 163 friend struct QueueUpdate; 164 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; 172 }; 173 status_t waitForCondition(const ConditionBase& condition); 174 175 struct UpdateBase { 176 SharedBufferStack& stack; 177 inline UpdateBase(SharedBufferBase* sbb) 178 : stack(*sbb->mSharedStack) { } 179 }; 180 template <typename T> 181 status_t updateCondition(T update); 182 }; 183 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(); 190 return result; 191 } 192 193 // ---------------------------------------------------------------------------- 194 195 class SharedBufferClient : public SharedBufferBase 196 { 197 public: 198 SharedBufferClient(SharedClient* sharedClient, int surface, int num, 199 int32_t identity); 200 201 ssize_t dequeue(); 202 status_t undoDequeue(int buf); 203 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); 211 212 class SetBufferCountCallback { 213 friend class SharedBufferClient; 214 virtual status_t operator()(int bufferCount) const = 0; 215 protected: 216 virtual ~SetBufferCountCallback() { } 217 }; 218 status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc); 219 220 private: 221 friend struct Condition; 222 friend struct DequeueCondition; 223 friend struct LockCondition; 224 225 struct QueueUpdate : public UpdateBase { 226 inline QueueUpdate(SharedBufferBase* sbb); 227 inline ssize_t operator()(); 228 }; 229 230 struct DequeueUpdate : public UpdateBase { 231 inline DequeueUpdate(SharedBufferBase* sbb); 232 inline ssize_t operator()(); 233 }; 234 235 struct CancelUpdate : public UpdateBase { 236 int tail, buf; 237 inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf); 238 inline ssize_t operator()(); 239 }; 240 241 // -- 242 243 struct DequeueCondition : public ConditionBase { 244 inline DequeueCondition(SharedBufferClient* sbc); 245 inline bool operator()() const; 246 inline const char* name() const { return "DequeueCondition"; } 247 }; 248 249 struct LockCondition : public ConditionBase { 250 int buf; 251 inline LockCondition(SharedBufferClient* sbc, int buf); 252 inline bool operator()() const; 253 inline const char* name() const { return "LockCondition"; } 254 }; 255 256 int32_t computeTail() const; 257 258 mutable RWLock mLock; 259 int mNumBuffers; 260 261 int32_t tail; 262 int32_t queued_head; 263 // statistics... 264 nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX]; 265 }; 266 267 // ---------------------------------------------------------------------------- 268 269 class SharedBufferServer 270 : public SharedBufferBase, 271 public LightRefBase<SharedBufferServer> 272 { 273 public: 274 SharedBufferServer(SharedClient* sharedClient, int surface, int num, 275 int32_t identity); 276 277 ssize_t retireAndLock(); 278 status_t unlock(int buffer); 279 void setStatus(status_t status); 280 status_t reallocateAll(); 281 status_t reallocateAllExcept(int buffer); 282 int32_t getQueuedCount() const; 283 Region getDirtyRegion(int buffer) const; 284 Rect getCrop(int buffer) const; 285 uint32_t getTransform(int buffer) const; 286 287 status_t resize(int newNumBuffers); 288 289 SharedBufferStack::Statistics getStats() const; 290 291 292 private: 293 friend class LightRefBase<SharedBufferServer>; 294 ~SharedBufferServer(); 295 296 /* 297 * BufferList is basically a fixed-capacity sorted-vector of 298 * unsigned 5-bits ints using a 32-bits int as storage. 299 * it has efficient iterators to find items in the list and not in the list. 300 */ 301 class BufferList { 302 size_t mCapacity; 303 uint32_t mList; 304 public: 305 BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX) 306 : mCapacity(c), mList(0) { } 307 status_t add(int value); 308 status_t remove(int value); 309 uint32_t getMask() const { return mList; } 310 311 class const_iterator { 312 friend class BufferList; 313 uint32_t mask, curr; 314 const_iterator(uint32_t mask) : 315 mask(mask), curr(__builtin_clz(mask)) { 316 } 317 public: 318 inline bool operator == (const const_iterator& rhs) const { 319 return mask == rhs.mask; 320 } 321 inline bool operator != (const const_iterator& rhs) const { 322 return mask != rhs.mask; 323 } 324 inline int operator *() const { return curr; } 325 inline const const_iterator& operator ++() { 326 mask &= ~(1<<(31-curr)); 327 curr = __builtin_clz(mask); 328 return *this; 329 } 330 }; 331 332 inline const_iterator begin() const { 333 return const_iterator(mList); 334 } 335 inline const_iterator end() const { 336 return const_iterator(0); 337 } 338 inline const_iterator free_begin() const { 339 uint32_t mask = (1 << (32-mCapacity)) - 1; 340 return const_iterator( ~(mList | mask) ); 341 } 342 }; 343 344 // this protects mNumBuffers and mBufferList 345 mutable RWLock mLock; 346 int mNumBuffers; 347 BufferList mBufferList; 348 349 struct UnlockUpdate : public UpdateBase { 350 const int lockedBuffer; 351 inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer); 352 inline ssize_t operator()(); 353 }; 354 355 struct RetireUpdate : public UpdateBase { 356 const int numBuffers; 357 inline RetireUpdate(SharedBufferBase* sbb, int numBuffers); 358 inline ssize_t operator()(); 359 }; 360 361 struct StatusUpdate : public UpdateBase { 362 const status_t status; 363 inline StatusUpdate(SharedBufferBase* sbb, status_t status); 364 inline ssize_t operator()(); 365 }; 366 }; 367 368 // =========================================================================== 369 370 struct display_cblk_t 371 { 372 uint16_t w; 373 uint16_t h; 374 uint8_t format; 375 uint8_t orientation; 376 uint8_t reserved[2]; 377 float fps; 378 float density; 379 float xdpi; 380 float ydpi; 381 uint32_t pad[2]; 382 }; 383 384 struct surface_flinger_cblk_t // 4KB max 385 { 386 uint8_t connected; 387 uint8_t reserved[3]; 388 uint32_t pad[7]; 389 display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX]; 390 }; 391 392 // --------------------------------------------------------------------------- 393 394 COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768) 395 COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096) 396 397 // --------------------------------------------------------------------------- 398 }; // namespace android 399 400 #endif /* ANDROID_SF_SHARED_BUFFER_STACK_H */ 401