diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/private/ui/LayerState.h | 2 | ||||
-rw-r--r-- | include/private/ui/SharedBufferStack.h | 327 | ||||
-rw-r--r-- | include/private/ui/SharedState.h | 154 | ||||
-rw-r--r-- | include/private/ui/SurfaceBuffer.h | 4 | ||||
-rw-r--r-- | include/ui/ISurface.h | 4 | ||||
-rw-r--r-- | include/ui/Surface.h | 19 | ||||
-rw-r--r-- | include/ui/SurfaceComposerClient.h | 18 | ||||
-rw-r--r-- | include/utils/Errors.h | 2 |
8 files changed, 352 insertions, 178 deletions
diff --git a/include/private/ui/LayerState.h b/include/private/ui/LayerState.h index b6fcd80..f1a2618 100644 --- a/include/private/ui/LayerState.h +++ b/include/private/ui/LayerState.h @@ -25,8 +25,6 @@ #include <ui/ISurfaceFlingerClient.h> #include <ui/Region.h> -#include <private/ui/SharedState.h> - namespace android { class Parcel; diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h new file mode 100644 index 0000000..2bd5344 --- /dev/null +++ b/include/private/ui/SharedBufferStack.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UI_SHARED_BUFFER_STACK_H +#define ANDROID_UI_SHARED_BUFFER_STACK_H + +#include <stdint.h> +#include <sys/types.h> + +#include <cutils/compiler.h> + +#include <utils/Debug.h> +#include <utils/threads.h> +#include <utils/String8.h> + +#include <ui/Rect.h> + +namespace android { +// --------------------------------------------------------------------------- + +/* + * These classes manage a stack of buffers in shared memory. + * + * SharedClient: represents a client with several stacks + * SharedBufferStack: represents a stack of buffers + * SharedBufferClient: manipulates the SharedBufferStack from the client side + * SharedBufferServer: manipulates the SharedBufferStack from the server side + * + * Buffers can be dequeued until there are none available, they can be locked + * unless they are in use by the server, which is only the case for the last + * dequeue-able buffer. When these various conditions are not met, the caller + * waits until the condition is met. + * + * + * CAVEATS: + * + * In the current implementation there are several limitations: + * - buffers must be locked in the same order they've been dequeued + * - buffers must be enqueued in the same order they've been locked + * - dequeue() is not reentrant + * - no error checks are done on the condition above + * + */ + +// When changing these values, the COMPILE_TIME_ASSERT at the end of this +// file need to be updated. +const unsigned int NUM_LAYERS_MAX = 31; +const unsigned int NUM_BUFFER_MAX = 4; +const unsigned int NUM_DISPLAY_MAX = 4; + +// ---------------------------------------------------------------------------- + +class Region; +class SharedBufferStack; +class SharedClient; + +// ---------------------------------------------------------------------------- + +struct FlatRegion { // 12 bytes + static const unsigned int NUM_RECT_MAX = 1; + uint32_t count; + uint16_t rects[4*NUM_RECT_MAX]; +}; + +// should be 128 bytes (32 longs) +class SharedBufferStack +{ + friend class SharedClient; + friend class SharedBufferBase; + friend class SharedBufferClient; + friend class SharedBufferServer; + +public: + SharedBufferStack(); + status_t setDirtyRegion(int buffer, const Region& reg); + Region getDirtyRegion(int buffer) const; + + // these attributes are part of the conditions/updates + volatile int32_t head; // server's current front buffer + volatile int32_t available; // number of dequeue-able buffers + volatile int32_t queued; // number of buffers waiting for post + volatile int32_t inUse; // buffer currently in use by SF + + // not part of the conditions + volatile int32_t reallocMask; + + int32_t identity; // surface's identity (const) + status_t status; // surface's status code + int32_t reserved32[13]; + FlatRegion dirtyRegion[NUM_BUFFER_MAX]; // 12*4=48 bytes +}; + +// ---------------------------------------------------------------------------- + +// 4 KB max +class SharedClient +{ +public: + SharedClient(); + ~SharedClient(); + + status_t validate(size_t token) const; + uint32_t getIdentity(size_t token) const; + status_t setIdentity(size_t token, uint32_t identity); + +private: + friend class SharedBufferBase; + friend class SharedBufferClient; + friend class SharedBufferServer; + + // FIXME: this should be replaced by a lock-less primitive + Mutex lock; + Condition cv; + SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; +}; + +// ============================================================================ + +class SharedBufferBase +{ +public: + SharedBufferBase(SharedClient* sharedClient, int surface, int num); + ~SharedBufferBase(); + uint32_t getIdentity(); + size_t getFrontBuffer() const; + String8 dump(char const* prefix) const; + +protected: + SharedClient* const mSharedClient; + SharedBufferStack* const mSharedStack; + const int mNumBuffers; + + friend struct Update; + friend struct QueueUpdate; + + struct ConditionBase { + SharedBufferStack& stack; + inline ConditionBase(SharedBufferBase* sbc) + : stack(*sbc->mSharedStack) { } + }; + + struct UpdateBase { + SharedBufferStack& stack; + inline UpdateBase(SharedBufferBase* sbb) + : stack(*sbb->mSharedStack) { } + }; + + template <typename T> + status_t waitForCondition(T condition); + + template <typename T> + status_t updateCondition(T update); +}; + +template <typename T> +status_t SharedBufferBase::waitForCondition(T condition) +{ + SharedClient& client( *mSharedClient ); + const nsecs_t TIMEOUT = s2ns(1); + Mutex::Autolock _l(client.lock); + while (!condition()) { + status_t err = client.cv.waitRelative(client.lock, TIMEOUT); + + // handle errors and timeouts + if (CC_UNLIKELY(err != NO_ERROR)) { + if (err == TIMED_OUT) { + if (condition()) { + LOGE("waitForCondition(%s) timed out (identity=%d), " + "but condition is true! We recovered but it " + "shouldn't happen." , + T::name(), mSharedStack->identity); + break; + } else { + LOGW("waitForCondition(%s) timed out (identity=%d). " + "CPU may be pegged. trying again.", + T::name(), mSharedStack->identity); + } + } else { + LOGE("waitForCondition(%s) error (%s) ", + T::name(), strerror(-err)); + return err; + } + } + } + return NO_ERROR; +} + + +template <typename T> +status_t SharedBufferBase::updateCondition(T update) { + SharedClient& client( *mSharedClient ); + Mutex::Autolock _l(client.lock); + ssize_t result = update(); + client.cv.broadcast(); + return result; +} + +// ---------------------------------------------------------------------------- + +class SharedBufferClient : public SharedBufferBase +{ +public: + SharedBufferClient(SharedClient* sharedClient, int surface, int num); + + ssize_t dequeue(); + status_t undoDequeue(int buf); + + status_t lock(int buf); + status_t queue(int buf); + bool needNewBuffer(int buffer) const; + status_t setDirtyRegion(int buffer, const Region& reg); + +private: + friend struct Condition; + friend struct DequeueCondition; + friend struct LockCondition; + + struct QueueUpdate : public UpdateBase { + inline QueueUpdate(SharedBufferBase* sbb); + inline ssize_t operator()(); + }; + + struct UndoDequeueUpdate : public UpdateBase { + inline UndoDequeueUpdate(SharedBufferBase* sbb); + inline ssize_t operator()(); + }; + + // -- + + struct DequeueCondition : public ConditionBase { + inline DequeueCondition(SharedBufferClient* sbc); + inline bool operator()(); + static inline const char* name() { return "DequeueCondition"; } + }; + + struct LockCondition : public ConditionBase { + int buf; + inline LockCondition(SharedBufferClient* sbc, int buf); + inline bool operator()(); + static inline const char* name() { return "LockCondition"; } + }; + + int32_t tail; +}; + +// ---------------------------------------------------------------------------- + +class SharedBufferServer : public SharedBufferBase +{ +public: + SharedBufferServer(SharedClient* sharedClient, int surface, int num); + + ssize_t retireAndLock(); + status_t unlock(int buffer); + status_t reallocate(); + status_t assertReallocate(int buffer); + + Region getDirtyRegion(int buffer) const; + +private: + struct UnlockUpdate : public UpdateBase { + const int lockedBuffer; + inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer); + inline ssize_t operator()(); + }; + + struct RetireUpdate : public UpdateBase { + const int numBuffers; + inline RetireUpdate(SharedBufferBase* sbb, int numBuffers); + inline ssize_t operator()(); + }; + + struct ReallocateCondition : public ConditionBase { + int buf; + inline ReallocateCondition(SharedBufferBase* sbb, int buf); + inline bool operator()(); + static inline const char* name() { return "ReallocateCondition"; } + }; +}; + +// =========================================================================== + +struct display_cblk_t +{ + uint16_t w; + uint16_t h; + uint8_t format; + uint8_t orientation; + uint8_t reserved[2]; + float fps; + float density; + float xdpi; + float ydpi; + uint32_t pad[2]; +}; + +struct surface_flinger_cblk_t // 4KB max +{ + uint8_t connected; + uint8_t reserved[3]; + uint32_t pad[7]; + display_cblk_t displays[NUM_DISPLAY_MAX]; +}; + +// --------------------------------------------------------------------------- + +COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096) +COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128) +COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096) + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif /* ANDROID_UI_SHARED_BUFFER_STACK_H */ diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h deleted file mode 100644 index c9f6b5e..0000000 --- a/include/private/ui/SharedState.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_UI_SHARED_STATE_H -#define ANDROID_UI_SHARED_STATE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Debug.h> -#include <utils/threads.h> - -namespace android { - -/* - * These structures are shared between the composer process and its clients - */ - -// --------------------------------------------------------------------------- - -struct surface_info_t { // 4 longs, 16 bytes - enum { - eBufferDirty = 0x01, - eNeedNewBuffer = 0x02 - }; - uint8_t reserved[11]; - uint8_t flags; - status_t status; -}; - -// --------------------------------------------------------------------------- - -const uint32_t NUM_LAYERS_MAX = 31; - -enum { // layer_cblk_t swapState - eIndex = 0x00000001, - eFlipRequested = 0x00000002, - - eResizeBuffer0 = 0x00000004, - eResizeBuffer1 = 0x00000008, - eResizeRequested = eResizeBuffer0 | eResizeBuffer1, - - eBusy = 0x00000010, - eLocked = 0x00000020, - eNextFlipPending = 0x00000040, - eInvalidSurface = 0x00000080 -}; - -enum { // layer_cblk_t flags - eLayerNotPosted = 0x00000001, - eNoCopyBack = 0x00000002, - eReserved = 0x0000007C, - eBufferIndexShift = 7, - eBufferIndex = 1<<eBufferIndexShift, -}; - -struct flat_region_t // 40 bytes -{ - int32_t count; - int16_t l; - int16_t t; - int16_t r; - int16_t b; - uint16_t runs[14]; -}; - -struct layer_cblk_t // (128 bytes) -{ - volatile int32_t swapState; // 4 - volatile int32_t flags; // 4 - volatile int32_t identity; // 4 - int32_t reserved; // 4 - surface_info_t surface[2]; // 32 - flat_region_t region[2]; // 80 - - static inline int backBuffer(uint32_t state) { - return ((state & eIndex) ^ ((state & eFlipRequested)>>1)); - } - static inline int frontBuffer(uint32_t state) { - return 1 - backBuffer(state); - } -}; - -// --------------------------------------------------------------------------- - -struct per_client_cblk_t // 4KB max -{ - per_client_cblk_t() : lock(Mutex::SHARED) { } - - Mutex lock; - Condition cv; - layer_cblk_t layers[NUM_LAYERS_MAX] __attribute__((aligned(32))); - - enum { - BLOCKING = 0x00000001, - INSPECT = 0x00000002 - }; - - // these functions are used by the clients - status_t validate(size_t i) const; - int32_t lock_layer(size_t i, uint32_t flags); - uint32_t unlock_layer_and_post(size_t i); - void unlock_layer(size_t i); -}; -// --------------------------------------------------------------------------- - -const uint32_t NUM_DISPLAY_MAX = 4; - -struct display_cblk_t -{ - uint16_t w; - uint16_t h; - uint8_t format; - uint8_t orientation; - uint8_t reserved[2]; - float fps; - float density; - float xdpi; - float ydpi; - uint32_t pad[2]; -}; - -struct surface_flinger_cblk_t // 4KB max -{ - uint8_t connected; - uint8_t reserved[3]; - uint32_t pad[7]; - display_cblk_t displays[NUM_DISPLAY_MAX]; -}; - -// --------------------------------------------------------------------------- - -COMPILE_TIME_ASSERT(sizeof(layer_cblk_t) == 128) -COMPILE_TIME_ASSERT(sizeof(per_client_cblk_t) <= 4096) -COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096) - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_UI_SHARED_STATE_H - diff --git a/include/private/ui/SurfaceBuffer.h b/include/private/ui/SurfaceBuffer.h index bf68406..73e517b 100644 --- a/include/private/ui/SurfaceBuffer.h +++ b/include/private/ui/SurfaceBuffer.h @@ -47,6 +47,9 @@ public: status_t lock(uint32_t usage, const Rect& rect, void** vaddr); status_t unlock(); + void setIndex(int index); + int getIndex() const; + protected: SurfaceBuffer(); SurfaceBuffer(const Parcel& reply); @@ -69,6 +72,7 @@ private: android_native_buffer_t const* buffer); BufferMapper& mBufferMapper; + int mIndex; }; }; // namespace android diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 7909c2f..1283033 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -44,13 +44,13 @@ protected: UNREGISTER_BUFFERS, POST_BUFFER, // one-way transaction CREATE_OVERLAY, - GET_BUFFER, + REQUEST_BUFFER, }; public: DECLARE_META_INTERFACE(Surface); - virtual sp<SurfaceBuffer> getBuffer(int usage) = 0; + virtual sp<SurfaceBuffer> requestBuffer(int bufferIdx, int usage) = 0; class BufferHeap { public: diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 30ab82f..118fb83 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -39,8 +39,8 @@ class IOMX; class Rect; class Surface; class SurfaceComposerClient; -struct per_client_cblk_t; -struct layer_cblk_t; +class SharedClient; +class SharedBufferClient; // --------------------------------------------------------------------------- @@ -109,7 +109,7 @@ private: ~SurfaceControl(); - status_t validate(per_client_cblk_t const* cblk) const; + status_t validate(SharedClient const* cblk) const; void destroy(); sp<SurfaceComposerClient> mClient; @@ -190,8 +190,7 @@ private: status_t getBufferLocked(int index, int usage); - status_t validate(per_client_cblk_t const* cblk) const; - static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); + status_t validate(SharedClient const* cblk) const; inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } inline BufferMapper& getBufferMapper() { return mBufferMapper; } @@ -210,11 +209,10 @@ private: int perform(int operation, va_list args); status_t dequeueBuffer(sp<SurfaceBuffer>* buffer); - status_t lockBuffer(const sp<SurfaceBuffer>& buffer); - status_t queueBuffer(const sp<SurfaceBuffer>& buffer); void setUsage(uint32_t reqUsage); + bool getUsage(uint32_t* usage); // constants sp<SurfaceComposerClient> mClient; @@ -224,21 +222,23 @@ private: PixelFormat mFormat; uint32_t mFlags; BufferMapper& mBufferMapper; + SharedBufferClient* mSharedBufferClient; // protected by mSurfaceLock Rect mSwapRectangle; uint32_t mUsage; - bool mUsageChanged; + int32_t mUsageChanged; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. sp<SurfaceBuffer> mBuffers[2]; mutable Region mDirtyRegion; - mutable uint8_t mBackbufferIndex; // must be used from the lock/unlock thread sp<SurfaceBuffer> mLockedBuffer; + sp<SurfaceBuffer> mPostedBuffer; mutable Region mOldDirtyRegion; + bool mNeedFullUpdate; // query() must be called from dequeueBuffer() thread uint32_t mWidth; @@ -246,6 +246,7 @@ private: // Inherently thread-safe mutable Mutex mSurfaceLock; + mutable Mutex mApiLock; }; }; // namespace android diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 286f885..269959c 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -21,7 +21,6 @@ #include <sys/types.h> #include <utils/SortedVector.h> -#include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <utils/threads.h> @@ -36,8 +35,7 @@ namespace android { class Region; class SurfaceFlingerSynchro; -struct per_client_cblk_t; -struct layer_cblk_t; +class SharedClient; class SurfaceComposerClient : virtual public RefBase { @@ -63,12 +61,12 @@ public: //! Create a surface sp<SurfaceControl> createSurface( - int pid, //!< pid of the process the surfacec is for - DisplayID display, //!< Display to create this surface on - uint32_t w, //!< width in pixel - uint32_t h, //!< height in pixel - PixelFormat format, //!< pixel-format desired - uint32_t flags = 0 //!< usage flags + int pid, // pid of the process the surface is for + DisplayID display, // Display to create this surface on + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0 // usage flags ); // ------------------------------------------------------------------------ @@ -148,7 +146,7 @@ private: // these don't need to be protected because they never change // after assignment status_t mStatus; - per_client_cblk_t* mControl; + SharedClient* mControl; sp<IMemoryHeap> mControlMemory; sp<ISurfaceFlingerClient> mClient; SurfaceFlingerSynchro* mSignalServer; diff --git a/include/utils/Errors.h b/include/utils/Errors.h index 1bf9e6f..81f818b 100644 --- a/include/utils/Errors.h +++ b/include/utils/Errors.h @@ -63,7 +63,7 @@ enum { BAD_INDEX = -EOVERFLOW, NOT_ENOUGH_DATA = -ENODATA, WOULD_BLOCK = -EWOULDBLOCK, - TIMED_OUT = -ETIME, + TIMED_OUT = -ETIMEDOUT, UNKNOWN_TRANSACTION = -EBADMSG, #else BAD_INDEX = -E2BIG, |