summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/private/ui/LayerState.h2
-rw-r--r--include/private/ui/SharedBufferStack.h327
-rw-r--r--include/private/ui/SharedState.h154
-rw-r--r--include/private/ui/SurfaceBuffer.h4
-rw-r--r--include/ui/ISurface.h4
-rw-r--r--include/ui/Surface.h19
-rw-r--r--include/ui/SurfaceComposerClient.h18
-rw-r--r--include/utils/Errors.h2
-rw-r--r--libs/surfaceflinger/Android.mk2
-rw-r--r--libs/surfaceflinger/Buffer.cpp (renamed from libs/surfaceflinger/LayerBitmap.cpp)109
-rw-r--r--libs/surfaceflinger/Buffer.h (renamed from libs/surfaceflinger/LayerBitmap.h)60
-rw-r--r--libs/surfaceflinger/BufferAllocator.cpp11
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp18
-rw-r--r--libs/surfaceflinger/Layer.cpp493
-rw-r--r--libs/surfaceflinger/Layer.h81
-rw-r--r--libs/surfaceflinger/LayerBase.cpp29
-rw-r--r--libs/surfaceflinger/LayerBase.h19
-rw-r--r--libs/surfaceflinger/LayerBuffer.cpp21
-rw-r--r--libs/surfaceflinger/LayerBuffer.h10
-rw-r--r--libs/surfaceflinger/LayerDim.cpp1
-rw-r--r--libs/surfaceflinger/LayerDim.h5
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp99
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h9
-rw-r--r--libs/ui/Android.mk2
-rw-r--r--libs/ui/ISurface.cpp10
-rw-r--r--libs/ui/SharedBufferStack.cpp352
-rw-r--r--libs/ui/Surface.cpp374
-rw-r--r--libs/ui/SurfaceBuffer.cpp134
-rw-r--r--libs/ui/SurfaceComposerClient.cpp184
29 files changed, 1278 insertions, 1275 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,
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index c4a70c8..49da111 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,12 +6,12 @@ LOCAL_SRC_FILES:= \
DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
BlurFilter.cpp.arm \
+ Buffer.cpp \
BufferAllocator.cpp \
Layer.cpp \
LayerBase.cpp \
LayerBuffer.cpp \
LayerBlur.cpp \
- LayerBitmap.cpp \
LayerDim.cpp \
MessageQueue.cpp \
SurfaceFlinger.cpp \
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/Buffer.cpp
index dd61e1a..4a7c55e 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/Buffer.cpp
@@ -27,8 +27,8 @@
#include <ui/Surface.h>
#include <pixelflinger/pixelflinger.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
@@ -38,15 +38,16 @@ namespace android {
// Buffer and implementation of android_native_buffer_t
// ===========================================================================
+Buffer::Buffer()
+ : SurfaceBuffer(), mInitCheck(NO_ERROR), mVStride(0)
+{
+}
+
Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format,
uint32_t reqUsage, uint32_t flags)
- : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags),
- mVStride(0)
+ : SurfaceBuffer(), mInitCheck(NO_INIT), mVStride(0)
{
- this->format = format;
- if (w>0 && h>0) {
- mInitCheck = initSize(w, h, reqUsage);
- }
+ mInitCheck = initSize(w, h, format, reqUsage, flags);
}
Buffer::~Buffer()
@@ -66,7 +67,19 @@ android_native_buffer_t* Buffer::getNativeBuffer() const
return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
}
-status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
+status_t Buffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
+ uint32_t reqUsage, uint32_t flags)
+{
+ if (handle) {
+ BufferAllocator& allocator(BufferAllocator::get());
+ allocator.free(handle);
+ handle = 0;
+ }
+ return initSize(w, h, f, reqUsage, flags);
+}
+
+status_t Buffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags)
{
status_t err = NO_ERROR;
@@ -84,7 +97,7 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
*
*/
- if (mFlags & Buffer::SECURE) {
+ if (flags & Buffer::SECURE) {
// secure buffer, don't store it into the GPU
usage = BufferAllocator::USAGE_SW_READ_OFTEN |
BufferAllocator::USAGE_SW_WRITE_OFTEN;
@@ -95,10 +108,10 @@ status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
}
err = allocator.alloc(w, h, format, usage, &handle, &stride);
-
if (err == NO_ERROR) {
- width = w;
- height = h;
+ this->width = w;
+ this->height = h;
+ this->format = format;
mVStride = 0;
}
@@ -121,78 +134,6 @@ status_t Buffer::lock(GGLSurface* sur, uint32_t usage)
return res;
}
-// ===========================================================================
-// LayerBitmap
-// ===========================================================================
-
-LayerBitmap::LayerBitmap()
- : mInfo(0), mWidth(0), mHeight(0)
-{
-}
-
-LayerBitmap::~LayerBitmap()
-{
-}
-
-status_t LayerBitmap::init(surface_info_t* info,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
-{
- if (info == NULL)
- return BAD_VALUE;
-
- mFormat = format;
- mFlags = flags;
- mWidth = w;
- mHeight = h;
-
- mInfo = info;
- memset(info, 0, sizeof(surface_info_t));
- info->flags = surface_info_t::eNeedNewBuffer;
-
- // init the buffer, but don't trigger an allocation
- mBuffer = new Buffer(0, 0, format, flags);
- return NO_ERROR;
-}
-
-status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
-{
- Mutex::Autolock _l(mLock);
- if ((w != mWidth) || (h != mHeight)) {
- mWidth = w;
- mHeight = h;
- // this will signal the client that it needs to asks us for a new buffer
- mInfo->flags = surface_info_t::eNeedNewBuffer;
- }
- return NO_ERROR;
-}
-
-sp<Buffer> LayerBitmap::allocate(uint32_t reqUsage)
-{
- Mutex::Autolock _l(mLock);
- surface_info_t* info = mInfo;
- mBuffer.clear(); // free buffer before allocating a new one
- sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, reqUsage, mFlags);
- status_t err = buffer->initCheck();
- if (LIKELY(err == NO_ERROR)) {
- info->flags = surface_info_t::eBufferDirty;
- info->status = NO_ERROR;
- } else {
- memset(info, 0, sizeof(surface_info_t));
- info->status = NO_MEMORY;
- }
- mBuffer = buffer;
- return buffer;
-}
-
-status_t LayerBitmap::free()
-{
- mBuffer.clear();
- mWidth = 0;
- mHeight = 0;
- return NO_ERROR;
-}
-
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/Buffer.h
index 87e8f42..79f4eeb 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/Buffer.h
@@ -30,7 +30,7 @@
#include <pixelflinger/pixelflinger.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/SurfaceBuffer.h>
class copybit_image_t;
@@ -38,10 +38,6 @@ struct android_native_buffer_t;
namespace android {
-// ---------------------------------------------------------------------------
-class IMemory;
-class LayerBitmap;
-
// ===========================================================================
// Buffer
// ===========================================================================
@@ -56,6 +52,8 @@ public:
SECURE = 0x00000004
};
+ Buffer();
+
// creates w * h buffer
Buffer(uint32_t w, uint32_t h, PixelFormat format,
uint32_t reqUsage, uint32_t flags = 0);
@@ -74,6 +72,9 @@ public:
android_native_buffer_t* getNativeBuffer() const;
+ status_t reallocate(uint32_t w, uint32_t h, PixelFormat f,
+ uint32_t reqUsage, uint32_t flags);
+
private:
friend class LightRefBase<Buffer>;
Buffer(const Buffer& rhs);
@@ -81,52 +82,11 @@ private:
Buffer& operator = (const Buffer& rhs);
const Buffer& operator = (const Buffer& rhs) const;
- status_t initSize(uint32_t w, uint32_t h, uint32_t reqUsage);
-
- ssize_t mInitCheck;
- uint32_t mFlags;
- uint32_t mVStride;
-};
-
-// ===========================================================================
-// LayerBitmap
-// ===========================================================================
+ status_t initSize(uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t reqUsage, uint32_t flags);
-class LayerBitmap
-{
-public:
- enum {
- DONT_CLEAR = Buffer::DONT_CLEAR,
- SECURE = Buffer::SECURE
- };
- LayerBitmap();
- ~LayerBitmap();
-
- status_t init(surface_info_t* info,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
-
- status_t setSize(uint32_t w, uint32_t h);
-
- sp<Buffer> allocate(uint32_t reqUsage);
- status_t free();
-
- sp<const Buffer> getBuffer() const { return mBuffer; }
- sp<Buffer> getBuffer() { return mBuffer; }
-
- uint32_t getWidth() const { return mWidth; }
- uint32_t getHeight() const { return mHeight; }
- PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); }
- Rect getBounds() const { return mBuffer->getBounds(); }
-
-private:
- surface_info_t* mInfo;
- sp<Buffer> mBuffer;
- uint32_t mWidth;
- uint32_t mHeight;
- PixelFormat mFormat;
- uint32_t mFlags;
- // protects setSize() and allocate()
- mutable Mutex mLock;
+ ssize_t mInitCheck;
+ uint32_t mVStride;
};
}; // namespace android
diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp
index cee8b64..19867a5 100644
--- a/libs/surfaceflinger/BufferAllocator.cpp
+++ b/libs/surfaceflinger/BufferAllocator.cpp
@@ -71,14 +71,23 @@ void BufferAllocator::dump(String8& result) const
result.append(buffer);
}
+static inline uint32_t clamp(uint32_t c) {
+ return c>0 ? c : 1;
+}
+
status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
int usage, buffer_handle_t* handle, int32_t* stride)
{
Mutex::Autolock _l(mLock);
-
+
+ // make sure to not allocate a 0 x 0 buffer
+ w = clamp(w);
+ h = clamp(h);
+
// we have a h/w allocator and h/w buffer is requested
status_t err = mAllocDev->alloc(mAllocDev,
w, h, format, usage, handle, stride);
+
LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
w, h, format, usage, err, strerror(-err));
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 3f607f6..651e7cf 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -46,22 +46,25 @@ using namespace android;
static __attribute__((noinline))
void checkGLErrors()
{
- GLenum error = glGetError();
- if (error != GL_NO_ERROR)
+ do {
+ // there could be more than one error flag
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR)
+ break;
LOGE("GL error 0x%04x", int(error));
+ } while(true);
}
static __attribute__((noinline))
void checkEGLErrors(const char* token)
{
EGLint error = eglGetError();
- // GLESonGL seems to be returning 0 when there is no errors?
- if (error && error != EGL_SUCCESS)
- LOGE("%s error 0x%04x (%s)",
+ if (error && error != EGL_SUCCESS) {
+ LOGE("%s: EGL error 0x%04x (%s)",
token, int(error), EGLUtils::strerror(error));
+ }
}
-
/*
* Initialize the display to the specified values.
*
@@ -158,7 +161,6 @@ void DisplayHardware::init(uint32_t dpy)
*/
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
- checkEGLErrors("eglCreateWindowSurface");
if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
if (dummy == EGL_BUFFER_PRESERVED) {
@@ -212,8 +214,6 @@ void DisplayHardware::init(uint32_t dpy)
*/
context = eglCreateContext(display, config, NULL, NULL);
- //checkEGLErrors("eglCreateContext");
-
/*
* Gather OpenGL ES extensions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 6f92515..ecb6b32 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -28,9 +28,9 @@
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
+#include "Buffer.h"
#include "clz.h"
#include "Layer.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -47,26 +47,29 @@ const char* const Layer::typeID = "Layer";
// ---------------------------------------------------------------------------
-Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i)
- : LayerBaseClient(flinger, display, c, i),
+Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& c, int32_t i)
+ : LayerBaseClient(flinger, display, c, i), lcblk(NULL),
mSecure(false),
- mFrontBufferIndex(1),
- mNeedsBlending(true),
- mResizeTransactionDone(false)
+ mNeedsBlending(true)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
+ lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS);
+ mFrontBufferIndex = lcblk->getFrontBuffer();
}
Layer::~Layer()
{
destroy();
// the actual buffers will be destroyed here
+ delete lcblk;
+
}
void Layer::destroy()
{
- for (int i=0 ; i<NUM_BUFFERS ; i++) {
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
if (mTextures[i].name != -1U) {
glDeleteTextures(1, &mTextures[i].name);
mTextures[i].name = -1U;
@@ -76,19 +79,11 @@ void Layer::destroy()
eglDestroyImageKHR(dpy, mTextures[i].image);
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
- mBuffers[i].free();
+ mBuffers[i].clear();
}
mSurface.clear();
}
-void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
-{
- LayerBase::initStates(w,h,flags);
-
- if (flags & ISurfaceComposer::eDestroyBackbuffer)
- lcblk->flags |= eNoCopyBack;
-}
-
sp<LayerBaseClient::Surface> Layer::createSurface() const
{
return mSurface;
@@ -112,13 +107,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
if (flags & ISurfaceComposer::eSecure)
bufferFlags |= Buffer::SECURE;
+ mFormat = format;
+ mWidth = w;
+ mHeight = h;
mSecure = (bufferFlags & Buffer::SECURE) ? true : false;
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
- for (int i=0 ; i<2 ; i++) {
- err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags);
- if (err != NO_ERROR) {
- return err;
- }
+ mBufferFlags = bufferFlags;
+ for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
+ mBuffers[i] = new Buffer();
}
mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
return NO_ERROR;
@@ -126,7 +122,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
void Layer::reloadTexture(const Region& dirty)
{
- const sp<Buffer>& buffer(frontBuffer().getBuffer());
+ Mutex::Autolock _l(mLock);
+ sp<Buffer> buffer(getFrontBuffer());
if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) {
int index = mFrontBufferIndex;
if (LIKELY(!mTextures[index].dirty)) {
@@ -202,80 +199,64 @@ void Layer::onDraw(const Region& clip) const
const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ?
mFrontBufferIndex : 0;
GLuint textureName = mTextures[index].name;
-
if (UNLIKELY(textureName == -1LU)) {
- LOGW("Layer %p doesn't have a texture", this);
+ //LOGW("Layer %p doesn't have a texture", this);
// the texture has not been created yet, this Layer has
// in fact never been drawn into. this happens frequently with
// SurfaceView.
clearWithOpenGL(clip);
return;
}
+
drawWithOpenGL(clip, mTextures[index]);
}
-sp<SurfaceBuffer> Layer::peekBuffer(int usage)
+sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage)
{
/*
- * This is called from the client's Surface::lock(), after it locked
- * the surface successfully. We're therefore guaranteed that the
- * back-buffer is not in use by ourselves.
- * Of course, we need to validate all this, which is not trivial.
- *
- * FIXME: A resize could happen at any time here. What to do about this?
- * - resize() form post()
- * - resize() from doTransaction()
- *
- * We'll probably need an internal lock for this.
- *
+ * This is called from the client's Surface::dequeue(). This can happen
+ * at any time, especially while we're in the middle of using the
+ * buffer 'index' as our front buffer.
*
- * TODO: We need to make sure that post() doesn't swap
- * the buffers under us.
+ * Make sure the buffer we're resizing is not the front buffer and has been
+ * dequeued. Once this condition is asserted, we are guaranteed that this
+ * buffer cannot become the front buffer under our feet, since we're called
+ * from Surface::dequeue()
*/
+ status_t err = lcblk->assertReallocate(index);
+ LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
- // it's okay to read swapState for the purpose of figuring out the
- // backbuffer index, which cannot change (since the app has locked it).
- const uint32_t state = lcblk->swapState;
- const int32_t backBufferIndex = layer_cblk_t::backBuffer(state);
+ Mutex::Autolock _l(mLock);
+ uint32_t w = mWidth;
+ uint32_t h = mHeight;
- // get rid of the EGL image, since we shouldn't need it anymore
- // (note that we're in a different thread than where it is being used)
- if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image);
- mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR;
+ sp<Buffer>& buffer(mBuffers[index]);
+ if (buffer->getStrongCount() == 1) {
+ err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
+ } else {
+ // here we have to reallocate a new buffer because we could have a
+ // client in our process with a reference to it (eg: status bar),
+ // and we can't release the handle under its feet.
+ buffer.clear();
+ buffer = new Buffer(w, h, mFormat, usage, mBufferFlags);
+ err = buffer->initCheck();
}
-
- LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
- sp<SurfaceBuffer> buffer = layerBitmap.allocate(usage);
-
- LOGD_IF(DEBUG_RESIZE,
- "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
- this, backBufferIndex,
- layerBitmap.getWidth(),
- layerBitmap.getHeight(),
- layerBitmap.getBuffer()->getWidth(),
- layerBitmap.getBuffer()->getHeight());
-
- if (UNLIKELY(buffer == 0)) {
- // XXX: what to do, what to do?
+
+ if (err || buffer->handle == 0) {
+ LOGE_IF(err || buffer->handle == 0,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
+ this, index, w, h, strerror(-err));
} else {
- // texture is now dirty...
- mTextures[backBufferIndex].dirty = true;
- // ... so it the visible region (because we consider the surface's
- // buffer size for visibility calculations)
- forceVisibilityTransaction();
- mFlinger->setTransactionFlags(eTraversalNeeded);
+ LOGD_IF(DEBUG_RESIZE,
+ "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d",
+ this, index, w, h);
}
- return buffer;
-}
-void Layer::scheduleBroadcast()
-{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
- mFlinger->scheduleBroadcast(ourClient);
+ if (err == NO_ERROR && buffer->handle != 0) {
+ // texture is now dirty...
+ mTextures[index].dirty = true;
}
+ return buffer;
}
uint32_t Layer::doTransaction(uint32_t flags)
@@ -283,114 +264,48 @@ uint32_t Layer::doTransaction(uint32_t flags)
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
- // the test front.{w|h} != temp.{w|h} is not enough because it is possible
- // that the size changed back to its previous value before the buffer
- // was resized (in the eLocked case below), in which case, we still
- // need to execute the code below so the clients have a chance to be
- // release. resize() deals with the fact that the size can be the same.
-
- /*
- * Various states we could be in...
-
- resize = state & eResizeRequested;
- if (backbufferChanged) {
- if (resize == 0) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == mask) {
- // ERROR one of the buffer has already been resized
- } else if (resize == mask ^ eResizeRequested) {
- // ERROR, the resized buffer doesn't have its resize flag set
- } else if (resize == eResizeRequested) {
- // OK, Normal case, proceed with resize
- }
- } else {
- if (resize == 0) {
- // OK, nothing special, do nothing
- } else if (resize == mask) {
- // restarted transaction, do nothing
- } else if (resize == mask ^ eResizeRequested) {
- // restarted transaction, do nothing
- } else if (resize == eResizeRequested) {
- // OK, size reset to previous value, proceed with resize
- }
- }
- */
-
// Index of the back buffer
const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
- const uint32_t state = lcblk->swapState;
- const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
- const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
- uint32_t resizeFlags = state & eResizeRequested;
-
- if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
- LOGE( "backbuffer size changed, but both resize flags are not set! "
- "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- int(temp.w), int(temp.h),
- int(drawingState().w), int(drawingState().h),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
- // if we get there we're pretty screwed. the only reasonable
- // thing to do is to pretend we should do the resize since
- // backbufferChanged is set (this also will give a chance to
- // client to get unblocked)
- resizeFlags = eResizeRequested;
- }
-
- if (resizeFlags == eResizeRequested) {
- // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
- // here, would be wrong and misleading because by this point
- // mFrontBufferIndex has not been updated yet.
+ if (backbufferChanged) {
+ // the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), state=%08x, "
- "requested (%dx%d), "
- "drawing (%d,%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, state,
- int(temp.w), int(temp.h),
+ "resize (layer=%p), requested (%dx%d), "
+ "drawing (%d,%d), (%dx%d), (%dx%d)",
+ this, int(temp.w), int(temp.h),
int(drawingState().w), int(drawingState().h),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- if (state & eLocked) {
- // if the buffer is locked, we can't resize anything because
- // - the backbuffer is currently in use by the user
- // - the front buffer is being shown
- // We just act as if the transaction didn't happen and we
- // reschedule it later...
- flags |= eRestartTransaction;
- } else {
- // This buffer needs to be resized
- status_t err =
- resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
- if (err == NO_ERROR) {
- const uint32_t mask = clientBackBufferIndex ?
- eResizeBuffer1 : eResizeBuffer0;
- android_atomic_and(~mask, &(lcblk->swapState));
- // since a buffer became available, we can let the client go...
- scheduleBroadcast();
- mResizeTransactionDone = true;
-
- // we're being resized and there is a freeze display request,
- // acquire a freeze lock, so that the screen stays put
- // until we've redrawn at the new size; this is to avoid
- // glitches upon orientation changes.
- if (mFlinger->hasFreezeRequest()) {
- // if the surface is hidden, don't try to acquire the
- // freeze lock, since hidden surfaces may never redraw
- if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
- mFreezeLock = mFlinger->getFreezeLock();
- }
- }
+ int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
+ int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
+
+ // record the new size, form this point on, when the client request a
+ // buffer, it'll get the new size.
+ setDrawingSize(temp.w, temp.h);
+
+ // all buffers need reallocation
+ lcblk->reallocate();
+
+ // recompute the visible region
+ // FIXME: ideally we would do that only when we have received
+ // a buffer of the right size
+ flags |= Layer::eVisibleRegion;
+ this->contentDirty = true;
+
+#if 0
+ // FIXME: handle freeze lock
+ // we're being resized and there is a freeze display request,
+ // acquire a freeze lock, so that the screen stays put
+ // until we've redrawn at the new size; this is to avoid
+ // glitches upon orientation changes.
+ if (mFlinger->hasFreezeRequest()) {
+ // if the surface is hidden, don't try to acquire the
+ // freeze lock, since hidden surfaces may never redraw
+ if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+ mFreezeLock = mFlinger->getFreezeLock();
}
}
+#endif
}
-
+
if (temp.sequence != front.sequence) {
if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
// this surface is now hidden, so it shouldn't hold a freeze lock
@@ -402,65 +317,10 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-status_t Layer::resize(
- int32_t clientBackBufferIndex,
- uint32_t width, uint32_t height,
- const char* what)
-{
- /*
- * handle resize (backbuffer and frontbuffer reallocation)
- * this is called from post() or from doTransaction()
- */
-
- const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
-
- // if the new (transaction) size is != from the the backbuffer
- // then we need to reallocate the backbuffer
- bool backbufferChanged = (clientBackBuffer.getWidth() != width) ||
- (clientBackBuffer.getHeight() != height);
-
- LOGD_IF(!backbufferChanged,
- "(%s) eResizeRequested (layer=%p), but size not changed: "
- "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
- "state=%08lx, index=%d, (%dx%d), (%dx%d)",
- what, this,
- int(width), int(height),
- int(drawingState().w), int(drawingState().h),
- int(currentState().w), int(currentState().h),
- long(lcblk->swapState),
- int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- // this can happen when changing the size back and forth quickly
- status_t err = NO_ERROR;
- if (backbufferChanged) {
-
- LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), requested (%dx%d), "
- "index=%d, (%dx%d), (%dx%d)",
- this, int(width), int(height), int(clientBackBufferIndex),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- err = mBuffers[clientBackBufferIndex].setSize(width, height);
- if (UNLIKELY(err != NO_ERROR)) {
- // This really should never happen
- LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
- clientBackBufferIndex, width, height, err, strerror(err));
- // couldn't reallocate the surface
- android_atomic_write(eInvalidSurface, &lcblk->swapState);
- }
- }
- return err;
-}
-
-void Layer::setSizeChanged(uint32_t w, uint32_t h)
-{
- LOGD_IF(DEBUG_RESIZE,
- "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
- w, h, mCurrentState.w, mCurrentState.h);
- android_atomic_or(eResizeRequested, &(lcblk->swapState));
+void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+ Mutex::Autolock _l(mLock);
+ mWidth = w;
+ mHeight = h;
}
// ----------------------------------------------------------------------------
@@ -469,139 +329,26 @@ void Layer::setSizeChanged(uint32_t w, uint32_t h)
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
- // preemptively block the client, because he might set
- // eFlipRequested at any time and want to use this buffer
- // for the next frame. This will be unset below if it
- // turns out we didn't need it.
-
- uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
- if (!(state & mask))
- return;
-
- if (UNLIKELY(state & eInvalidSurface)) {
- // if eInvalidSurface is set, this means the surface
- // became invalid during a transaction (NO_MEMORY for instance)
- scheduleBroadcast();
+ ssize_t buf = lcblk->retireAndLock();
+ if (buf < NO_ERROR) {
+ //LOGW("nothing to retire (%s)", strerror(-buf));
+ // NOTE: here the buffer is locked because we will used
+ // for composition later in the loop
return;
}
-
- if (UNLIKELY(state & eFlipRequested)) {
- uint32_t oldState;
- mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
- if (oldState & eNextFlipPending) {
- // Process another round (we know at least a buffer
- // is ready for that client).
- mFlinger->signalEvent();
- }
- }
-}
-
-Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
-{
- // atomically swap buffers and (re)set eFlipRequested
- int32_t oldValue, newValue;
- layer_cblk_t * const lcblk = this->lcblk;
- do {
- oldValue = lcblk->swapState;
- // get the current value
-
- LOG_ASSERT(oldValue&eFlipRequested,
- "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
- long(oldValue));
-
- newValue = (oldValue ^ eIndex);
- // swap buffers
-
- newValue &= ~(eFlipRequested | eNextFlipPending);
- // clear eFlipRequested and eNextFlipPending
-
- if (oldValue & eNextFlipPending)
- newValue |= eFlipRequested;
- // if eNextFlipPending is set (second buffer already has something
- // in it) we need to reset eFlipRequested because the client
- // might never do it
-
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- *previousSate = oldValue;
- const int32_t index = (newValue & eIndex) ^ 1;
- mFrontBufferIndex = index;
+ // we retired a buffer, which becomes the new front buffer
+ mFrontBufferIndex = buf;
- /* NOTE: it's safe to set this flag here because this is only touched
- * from LayerBitmap::allocate(), which by construction cannot happen
- * while we're in post().
- */
- lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty;
-
- // ... post the new front-buffer
- Region dirty(lcblk->region + index);
- dirty.andSelf(frontBuffer().getBounds());
-
- //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
- // oldValue, newValue, mFrontBufferIndex);
- //dirty.dump("dirty");
+ // get the dirty region
+ sp<Buffer> newFrontBuffer(getBuffer(buf));
+ const Region dirty(lcblk->getDirtyRegion(buf));
+ mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
- if (UNLIKELY(oldValue & eResizeRequested)) {
-
- LOGD_IF(DEBUG_RESIZE,
- "post (layer=%p), state=%08x, "
- "index=%d, (%dx%d), (%dx%d)",
- this, newValue,
- int(1-index),
- int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()),
- int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight()));
-
- // here, we just posted the surface and we have resolved
- // the front/back buffer indices. The client is blocked, so
- // it cannot start using the new backbuffer.
-
- // If the backbuffer was resized in THIS round, we actually cannot
- // resize the frontbuffer because it has *just* been drawn (and we
- // would have nothing to draw). In this case we just skip the resize
- // it'll happen after the next page flip or during the next
- // transaction.
-
- const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
- if (mResizeTransactionDone && (newValue & mask)) {
- // Resize the layer's second buffer only if the transaction
- // happened. It may not have happened yet if eResizeRequested
- // was set immediately after the "transactionRequested" test,
- // in which case the drawing state's size would be wrong.
- mFreezeLock.clear();
- const Layer::State& s(drawingState());
- if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
- do {
- oldValue = lcblk->swapState;
- if ((oldValue & eResizeRequested) == eResizeRequested) {
- // ugh, another resize was requested since we processed
- // the first buffer, don't free the client, and let
- // the next transaction handle everything.
- break;
- }
- newValue = oldValue & ~mask;
- } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
- }
- mResizeTransactionDone = false;
- recomputeVisibleRegions = true;
- this->contentDirty = true;
- }
- }
+ // FIXME: signal an event if we have more buffers waiting
+ // mFlinger->signalEvent();
- reloadTexture(dirty);
-
- return dirty;
-}
-
-Point Layer::getPhysicalSize() const
-{
- sp<const Buffer> front(frontBuffer().getBuffer());
- Point size(front->getWidth(), front->getHeight());
- if ((size.x | size.y) == 0) {
- // if we don't have a buffer yet, just use the state's size.
- size = LayerBase::getPhysicalSize();
- }
- return size;
+ reloadTexture( mPostedDirtyRegion );
}
void Layer::unlockPageFlip(
@@ -622,21 +369,15 @@ void Layer::unlockPageFlip(
// is in screen space as well).
dirtyRegion.andSelf(visibleRegionScreen);
outDirtyRegion.orSelf(dirtyRegion);
-
- // client could be blocked, so signal them so they get a
- // chance to reevaluate their condition.
- scheduleBroadcast();
}
}
void Layer::finishPageFlip()
{
- if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
- LOGE_IF(!(lcblk->swapState & eBusy),
- "layer %p wasn't locked!", this);
- android_atomic_and(~eBusy, &(lcblk->swapState));
- }
- scheduleBroadcast();
+ status_t err = lcblk->unlock( mFrontBufferIndex );
+ LOGE_IF(err!=NO_ERROR,
+ "layer %p, buffer=%d wasn't locked!",
+ this, mFrontBufferIndex);
}
// ---------------------------------------------------------------------------
@@ -651,12 +392,16 @@ Layer::SurfaceLayer::~SurfaceLayer()
{
}
-sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer(int usage)
+sp<SurfaceBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
{
- sp<SurfaceBuffer> buffer = 0;
+ sp<SurfaceBuffer> buffer;
sp<Layer> owner(getOwner());
if (owner != 0) {
- buffer = owner->peekBuffer(usage);
+ LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
+ "getBuffer() index (%d) out of range", index);
+ if (uint32_t(index) < NUM_BUFFERS) {
+ buffer = owner->requestBuffer(index, usage);
+ }
}
return buffer;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index add5d50..3b4489e 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -21,10 +21,6 @@
#include <sys/types.h>
#include <ui/PixelFormat.h>
-
-#include <private/ui/SharedState.h>
-#include <private/ui/LayerState.h>
-
#include <pixelflinger/pixelflinger.h>
#include <EGL/egl.h>
@@ -32,7 +28,7 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
-#include "LayerBitmap.h"
+#include "Buffer.h"
#include "LayerBase.h"
#include "Transform.h"
@@ -41,12 +37,12 @@ namespace android {
// ---------------------------------------------------------------------------
class Client;
-class LayerBitmap;
class FreezeLock;
+class Buffer;
// ---------------------------------------------------------------------------
-const int NUM_BUFFERS = 2;
+const size_t NUM_BUFFERS = 2;
class Layer : public LayerBaseClient
{
@@ -56,23 +52,22 @@ public:
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+
+ SharedBufferServer* lcblk;
+
+
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~Layer();
- inline PixelFormat pixelFormat() const {
- return frontBuffer().getPixelFormat();
- }
+ status_t setBuffers(uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags=0);
- status_t setBuffers( uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags=0);
+ void setDrawingSize(uint32_t w, uint32_t h);
virtual void onDraw(const Region& clip) const;
- virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
- virtual void setSizeChanged(uint32_t w, uint32_t h);
virtual uint32_t doTransaction(uint32_t transactionFlags);
- virtual Point getPhysicalSize() const;
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
virtual void finishPageFlip();
@@ -80,42 +75,31 @@ public:
virtual bool isSecure() const { return mSecure; }
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
-
- const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; }
- LayerBitmap& getBuffer(int i) { return mBuffers[i]; }
-
+
// only for debugging
- const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ inline sp<Buffer> getBuffer(int i) { return mBuffers[i]; }
+ // only for debugging
+ inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
+ // only for debugging
+ inline PixelFormat pixelFormat() const { return mFormat; }
private:
- inline const LayerBitmap&
- frontBuffer() const { return getBuffer(mFrontBufferIndex); }
- inline LayerBitmap&
- frontBuffer() { return getBuffer(mFrontBufferIndex); }
- inline const LayerBitmap&
- backBuffer() const { return getBuffer(1-mFrontBufferIndex); }
- inline LayerBitmap&
- backBuffer() { return getBuffer(1-mFrontBufferIndex); }
-
+ inline sp<Buffer> getFrontBuffer() {
+ return mBuffers[mFrontBufferIndex];
+ }
+
void reloadTexture(const Region& dirty);
- status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
- Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
- sp<SurfaceBuffer> peekBuffer(int usage);
+ sp<SurfaceBuffer> requestBuffer(int index, int usage);
void destroy();
- void scheduleBroadcast();
-
- class SurfaceLayer : public LayerBaseClient::Surface
- {
+ class SurfaceLayer : public LayerBaseClient::Surface {
public:
- SurfaceLayer(const sp<SurfaceFlinger>& flinger,
- SurfaceID id, const sp<Layer>& owner);
- ~SurfaceLayer();
-
+ SurfaceLayer(const sp<SurfaceFlinger>& flinger,
+ SurfaceID id, const sp<Layer>& owner);
+ ~SurfaceLayer();
private:
- virtual sp<SurfaceBuffer> getBuffer(int usage);
-
+ virtual sp<SurfaceBuffer> requestBuffer(int index, int usage);
sp<Layer> getOwner() const {
return static_cast<Layer*>(Surface::getOwner().get());
}
@@ -125,13 +109,20 @@ private:
sp<Surface> mSurface;
bool mSecure;
- LayerBitmap mBuffers[NUM_BUFFERS];
- Texture mTextures[NUM_BUFFERS];
int32_t mFrontBufferIndex;
bool mNeedsBlending;
- bool mResizeTransactionDone;
Region mPostedDirtyRegion;
sp<FreezeLock> mFreezeLock;
+ PixelFormat mFormat;
+ uint32_t mBufferFlags;
+
+ // protected by mLock
+ sp<Buffer> mBuffers[NUM_BUFFERS];
+ Texture mTextures[NUM_BUFFERS];
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index ec38fe9..62e41b0 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -30,7 +30,6 @@
#include "clz.h"
#include "LayerBase.h"
-#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -127,9 +126,6 @@ uint32_t LayerBase::setTransactionFlags(uint32_t flags) {
return android_atomic_or(flags, &mTransactionFlags);
}
-void LayerBase::setSizeChanged(uint32_t w, uint32_t h) {
-}
-
bool LayerBase::setPosition(int32_t x, int32_t y) {
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
return false;
@@ -149,7 +145,6 @@ bool LayerBase::setLayer(uint32_t z) {
bool LayerBase::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.w == w && mCurrentState.h == h)
return false;
- setSizeChanged(w, h);
mCurrentState.w = w;
mCurrentState.h = h;
requestTransaction();
@@ -219,21 +214,14 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
return flags;
}
-Point LayerBase::getPhysicalSize() const
-{
- const Layer::State& front(drawingState());
- return Point(front.w, front.h);
-}
-
void LayerBase::validateVisibility(const Transform& planeTransform)
{
const Layer::State& s(drawingState());
const Transform tr(planeTransform * s.transform);
const bool transformed = tr.transformed();
- const Point size(getPhysicalSize());
- uint32_t w = size.x;
- uint32_t h = size.y;
+ uint32_t w = s.w;
+ uint32_t h = s.h;
tr.transform(mVertices[0], 0, 0);
tr.transform(mVertices[1], 0, h);
tr.transform(mVertices[2], w, h);
@@ -655,9 +643,7 @@ int32_t LayerBaseClient::sIdentity = 0;
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBase(flinger, display), client(client),
- lcblk( client!=0 ? &(client->ctrlblk->layers[i]) : 0 ),
- mIndex(i),
- mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
+ mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
}
@@ -666,11 +652,8 @@ void LayerBaseClient::onFirstRef()
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
- // Initialize this layer's control block
- memset(this->lcblk, 0, sizeof(layer_cblk_t));
- this->lcblk->identity = mIdentity;
- Region::writeEmpty(&(this->lcblk->region[0]), sizeof(flat_region_t));
- Region::writeEmpty(&(this->lcblk->region[1]), sizeof(flat_region_t));
+ // Initialize this layer's identity
+ client->ctrlblk->setIdentity(mIndex, mIdentity);
}
}
@@ -759,7 +742,7 @@ status_t LayerBaseClient::Surface::onTransact(
return BnSurface::onTransact(code, data, reply, flags);
}
-sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer(int)
+sp<SurfaceBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
{
return NULL;
}
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 2168de0..78bb4bf 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -23,6 +23,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include <utils/RefBase.h>
@@ -137,11 +138,6 @@ public:
virtual void initStates(uint32_t w, uint32_t h, uint32_t flags);
/**
- * setSizeChanged - called when the *current* state's size is changed.
- */
- virtual void setSizeChanged(uint32_t w, uint32_t h);
-
- /**
* doTransaction - process the transaction. This is a good place to figure
* out which attributes of the surface have changed.
*/
@@ -161,13 +157,6 @@ public:
virtual void setCoveredRegion(const Region& coveredRegion);
/**
- * getPhysicalSize - returns the physical size of the drawing state of
- * the surface. If the surface is backed by a bitmap, this is the size of
- * the bitmap (as opposed to the size of the drawing state).
- */
- virtual Point getPhysicalSize() const;
-
- /**
* validateVisibility - cache a bunch of things
*/
virtual void validateVisibility(const Transform& globalTransform);
@@ -308,8 +297,8 @@ public:
virtual ~LayerBaseClient();
virtual void onFirstRef();
- wp<Client> client;
- layer_cblk_t* const lcblk;
+ wp<Client> client;
+// SharedBufferServer* lcblk;
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
@@ -336,7 +325,7 @@ public:
sp<LayerBaseClient> getOwner() const;
private:
- virtual sp<SurfaceBuffer> getBuffer(int usage);
+ virtual sp<SurfaceBuffer> requestBuffer(int index, int usage);
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
virtual void unregisterBuffers();
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 8a55a3f..433b48e 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -28,6 +28,7 @@
#include <hardware/copybit.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "LayerBuffer.h"
#include "SurfaceFlinger.h"
@@ -58,7 +59,7 @@ LayerBuffer::~LayerBuffer()
void LayerBuffer::onFirstRef()
{
LayerBaseClient::onFirstRef();
- mSurface = new SurfaceBuffer(mFlinger, clientIndex(),
+ mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(),
const_cast<LayerBuffer *>(this));
}
@@ -181,21 +182,21 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() {
}
// ============================================================================
-// LayerBuffer::SurfaceBuffer
+// LayerBuffer::SurfaceLayerBuffer
// ============================================================================
-LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<LayerBuffer>& owner)
: LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner)
{
}
-LayerBuffer::SurfaceBuffer::~SurfaceBuffer()
+LayerBuffer::SurfaceLayerBuffer::~SurfaceLayerBuffer()
{
unregisterBuffers();
}
-status_t LayerBuffer::SurfaceBuffer::registerBuffers(
+status_t LayerBuffer::SurfaceLayerBuffer::registerBuffers(
const ISurface::BufferHeap& buffers)
{
sp<LayerBuffer> owner(getOwner());
@@ -204,21 +205,21 @@ status_t LayerBuffer::SurfaceBuffer::registerBuffers(
return NO_INIT;
}
-void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset)
+void LayerBuffer::SurfaceLayerBuffer::postBuffer(ssize_t offset)
{
sp<LayerBuffer> owner(getOwner());
if (owner != 0)
owner->postBuffer(offset);
}
-void LayerBuffer::SurfaceBuffer::unregisterBuffers()
+void LayerBuffer::SurfaceLayerBuffer::unregisterBuffers()
{
sp<LayerBuffer> owner(getOwner());
if (owner != 0)
owner->unregisterBuffers();
}
-sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay(
+sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(
uint32_t w, uint32_t h, int32_t format) {
sp<OverlayRef> result;
sp<LayerBuffer> owner(getOwner());
@@ -462,8 +463,8 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
const int tmp_h = floorf(src_height * yscale);
if (mTempBitmap==0 ||
- mTempBitmap->getWidth() < tmp_w ||
- mTempBitmap->getHeight() < tmp_h) {
+ mTempBitmap->getWidth() < size_t(tmp_w) ||
+ mTempBitmap->getHeight() < size_t(tmp_h)) {
mTempBitmap.clear();
mTempBitmap = new android::Buffer(
tmp_w, tmp_h, src.img.format,
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 8057219..e539f68 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -24,7 +24,6 @@
#include <private/ui/LayerState.h>
#include "LayerBase.h"
-#include "LayerBitmap.h"
struct copybit_device_t;
@@ -32,9 +31,12 @@ namespace android {
// ---------------------------------------------------------------------------
+class Buffer;
class Region;
class OverlayRef;
+// ---------------------------------------------------------------------------
+
class LayerBuffer : public LayerBaseClient
{
class Source : public LightRefBase<Source> {
@@ -179,12 +181,12 @@ private:
};
- class SurfaceBuffer : public LayerBaseClient::Surface
+ class SurfaceLayerBuffer : public LayerBaseClient::Surface
{
public:
- SurfaceBuffer(const sp<SurfaceFlinger>& flinger,
+ SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<LayerBuffer>& owner);
- virtual ~SurfaceBuffer();
+ virtual ~SurfaceLayerBuffer();
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
virtual void postBuffer(ssize_t offset);
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index f613767..8ba0a9d 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -21,6 +21,7 @@
#include <utils/Errors.h>
#include <utils/Log.h>
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "LayerDim.h"
#include "SurfaceFlinger.h"
diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h
index 33bd49d..d4672a1 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/libs/surfaceflinger/LayerDim.h
@@ -24,12 +24,11 @@
#include <EGL/eglext.h>
#include "LayerBase.h"
-#include "LayerBitmap.h"
-
-namespace android {
// ---------------------------------------------------------------------------
+namespace android {
+
class LayerDim : public LayerBaseClient
{
static bool sUseTexture;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index c78921a..b368db6 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -44,12 +44,12 @@
#include <GLES/gl.h>
#include "clz.h"
+#include "Buffer.h"
#include "BufferAllocator.h"
#include "Layer.h"
#include "LayerBlur.h"
#include "LayerBuffer.h"
#include "LayerDim.h"
-#include "LayerBitmap.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
@@ -173,12 +173,12 @@ SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
mTransactionCount(0),
+ mResizeTransationPending(false),
mLayersRemoved(false),
mBootTime(systemTime()),
mHardwareTest("android.permission.HARDWARE_TEST"),
mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
mDump("android.permission.DUMP"),
- mLastScheduledBroadcast(NULL),
mVisibleRegionsDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
@@ -497,13 +497,11 @@ bool SurfaceFlinger::threadLoop()
// release the clients before we flip ('cause flip might block)
unlockClients();
- executeScheduledBroadcasts();
postFramebuffer();
} else {
// pretend we did the post
unlockClients();
- executeScheduledBroadcasts();
usleep(16667); // 60 fps period
}
return true;
@@ -773,7 +771,8 @@ void SurfaceFlinger::computeVisibleRegions(
void SurfaceFlinger::commitTransaction()
{
mDrawingState = mCurrentState;
- mTransactionCV.signal();
+ mResizeTransationPending = false;
+ mTransactionCV.broadcast();
}
void SurfaceFlinger::handlePageFlip()
@@ -910,37 +909,6 @@ void SurfaceFlinger::unlockClients()
}
}
-void SurfaceFlinger::scheduleBroadcast(const sp<Client>& client)
-{
- if (mLastScheduledBroadcast != client) {
- mLastScheduledBroadcast = client;
- mScheduledBroadcasts.add(client);
- }
-}
-
-void SurfaceFlinger::executeScheduledBroadcasts()
-{
- SortedVector< wp<Client> >& list(mScheduledBroadcasts);
- size_t count = list.size();
- while (count--) {
- sp<Client> client = list[count].promote();
- if (client != 0) {
- per_client_cblk_t* const cblk = client->ctrlblk;
- if (cblk->lock.tryLock() == NO_ERROR) {
- cblk->cv.broadcast();
- list.removeAt(count);
- cblk->lock.unlock();
- } else {
- // schedule another round
- LOGW("executeScheduledBroadcasts() skipped, "
- "contention on the client. We'll try again later...");
- signalDelayedEvent(ms2ns(4));
- }
- }
- }
- mLastScheduledBroadcast = 0;
-}
-
void SurfaceFlinger::debugFlashRegions()
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
@@ -1129,18 +1097,10 @@ void SurfaceFlinger::free_resources_l()
mLayersRemoved = false;
// free resources associated with disconnected clients
- SortedVector< wp<Client> >& scheduledBroadcasts(mScheduledBroadcasts);
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
for (size_t i=0 ; i<count ; i++) {
sp<Client> client = disconnectedClients[i];
- // if this client is the scheduled broadcast list,
- // remove it from there (and we don't need to signal it
- // since it is dead).
- int32_t index = scheduledBroadcasts.indexOf(client);
- if (index >= 0) {
- scheduledBroadcasts.removeItemsAt(index);
- }
mTokens.release(client->cid);
}
disconnectedClients.clear();
@@ -1173,6 +1133,13 @@ void SurfaceFlinger::closeGlobalTransaction()
{
if (android_atomic_dec(&mTransactionCount) == 1) {
signalEvent();
+
+ // if there is a transaction with a resize, wait for it to
+ // take effect before returning.
+ Mutex::Autolock _l(mStateLock);
+ while (mResizeTransationPending) {
+ mTransactionCV.wait(mStateLock);
+ }
}
}
@@ -1424,8 +1391,10 @@ status_t SurfaceFlinger::setClientState(
}
}
if (what & eSizeChanged) {
- if (layer->setSize(s.w, s.h))
+ if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
+ mResizeTransationPending = true;
+ }
}
if (what & eAlphaChanged) {
if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
@@ -1543,28 +1512,27 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
"id=0x%08x, client=0x%08x, identity=%u\n",
lbc->clientIndex(), client.get() ? client->cid : 0,
lbc->getIdentity());
+
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
/*** Layer ***/
sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
if (l != 0) {
- const LayerBitmap& buf0(l->getBuffer(0));
- const LayerBitmap& buf1(l->getBuffer(1));
+ result.append( l->lcblk->dump(" ") );
+ sp<const Buffer> buf0(l->getBuffer(0));
+ sp<const Buffer> buf1(l->getBuffer(1));
snprintf(buffer, SIZE,
" "
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, swapState=0x%08x\n",
+ " freezeLock=%p\n",
l->pixelFormat(),
- buf0.getWidth(), buf0.getHeight(),
- buf0.getBuffer()->getStride(),
- buf1.getWidth(), buf1.getHeight(),
- buf1.getBuffer()->getStride(),
- l->getFreezeLock().get(),
- l->lcblk->swapState);
+ buf0->getWidth(), buf0->getHeight(), buf0->getStride(),
+ buf1->getWidth(), buf1->getHeight(), buf1->getStride(),
+ l->getFreezeLock().get());
+ result.append(buffer);
+ buffer[0] = 0;
}
- result.append(buffer);
- buffer[0] = 0;
s.transparentRegion.dump(result, "transparentRegion");
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
@@ -1657,8 +1625,12 @@ status_t SurfaceFlinger::onTransact(
const DisplayHardware& hw(graphicPlane(0).displayHardware());
mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
signalEvent();
+ return NO_ERROR;
+ }
+ case 1005:{ // force transaction
+ setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
+ return NO_ERROR;
}
- return NO_ERROR;
case 1007: // set mFreezeCount
mFreezeCount = data.readInt32();
return NO_ERROR;
@@ -1688,21 +1660,20 @@ Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
: ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
{
const int pgsize = getpagesize();
- const int cblksize = ((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));
+ const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
mCblkHeap = new MemoryHeapBase(cblksize, 0,
"SurfaceFlinger Client control-block");
- ctrlblk = static_cast<per_client_cblk_t *>(mCblkHeap->getBase());
+ ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) per_client_cblk_t;
+ new(ctrlblk) SharedClient;
}
}
Client::~Client() {
if (ctrlblk) {
- const int pgsize = getpagesize();
- ctrlblk->~per_client_cblk_t(); // destroy our shared-structure.
+ ctrlblk->~SharedClient(); // destroy our shared-structure.
}
}
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 69e2f2e..f207f85 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -34,7 +34,7 @@
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include "Barrier.h"
@@ -87,7 +87,7 @@ public:
}
// pointer to this client's control block
- per_client_cblk_t* ctrlblk;
+ SharedClient* ctrlblk;
ClientID cid;
@@ -268,8 +268,6 @@ private:
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
void handleRepaint();
- void scheduleBroadcast(const sp<Client>& client);
- void executeScheduledBroadcasts();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
void unlockClients();
@@ -313,6 +311,7 @@ private:
volatile int32_t mTransactionFlags;
volatile int32_t mTransactionCount;
Condition mTransactionCV;
+ bool mResizeTransationPending;
// protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
@@ -337,8 +336,6 @@ private:
Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
- wp<Client> mLastScheduledBroadcast;
- SortedVector< wp<Client> > mScheduledBroadcasts;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 93c7263..348dd68 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -23,7 +23,9 @@ LOCAL_SRC_FILES:= \
PixelFormat.cpp \
Rect.cpp \
Region.cpp \
+ SharedBufferStack.cpp \
Surface.cpp \
+ SurfaceBuffer.cpp \
SurfaceComposerClient.cpp \
SurfaceFlingerSynchro.cpp
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index b78e8b5..a2dbe7f 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -71,12 +71,13 @@ public:
{
}
- virtual sp<SurfaceBuffer> getBuffer(int usage)
+ virtual sp<SurfaceBuffer> requestBuffer(int bufferIdx, int usage)
{
Parcel data, reply;
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+ data.writeInt32(bufferIdx);
data.writeInt32(usage);
- remote()->transact(GET_BUFFER, data, &reply);
+ remote()->transact(REQUEST_BUFFER, data, &reply);
sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
return buffer;
}
@@ -134,10 +135,11 @@ status_t BnSurface::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case GET_BUFFER: {
+ case REQUEST_BUFFER: {
CHECK_INTERFACE(ISurface, data, reply);
+ int bufferIdx = data.readInt32();
int usage = data.readInt32();
- sp<SurfaceBuffer> buffer(getBuffer(usage));
+ sp<SurfaceBuffer> buffer(requestBuffer(bufferIdx, usage));
return SurfaceBuffer::writeToParcel(reply, buffer.get());
}
case REGISTER_BUFFERS: {
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
new file mode 100644
index 0000000..5995af5
--- /dev/null
+++ b/libs/ui/SharedBufferStack.cpp
@@ -0,0 +1,352 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SharedBufferStack"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <private/ui/SharedBufferStack.h>
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#define DEBUG_ATOMICS 0
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+SharedClient::SharedClient()
+ : lock(Mutex::SHARED)
+{
+}
+
+SharedClient::~SharedClient() {
+}
+
+
+// these functions are used by the clients
+status_t SharedClient::validate(size_t i) const {
+ if (uint32_t(i) >= uint32_t(NUM_LAYERS_MAX))
+ return BAD_INDEX;
+ return surfaces[i].status;
+}
+
+uint32_t SharedClient::getIdentity(size_t token) const {
+ return uint32_t(surfaces[token].identity);
+}
+
+status_t SharedClient::setIdentity(size_t token, uint32_t identity) {
+ if (token >= NUM_LAYERS_MAX)
+ return BAD_INDEX;
+ surfaces[token].identity = identity;
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+
+SharedBufferStack::SharedBufferStack()
+ : inUse(-1), identity(-1), status(NO_ERROR)
+{
+}
+
+status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
+{
+ if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+ return BAD_INDEX;
+
+ // in the current implementation we only send a single rectangle
+ const Rect bounds(dirty.getBounds());
+ FlatRegion& reg(dirtyRegion[buffer]);
+ reg.count = 1;
+ reg.rects[0] = uint16_t(bounds.left);
+ reg.rects[1] = uint16_t(bounds.top);
+ reg.rects[2] = uint16_t(bounds.right);
+ reg.rects[3] = uint16_t(bounds.bottom);
+ return NO_ERROR;
+}
+
+Region SharedBufferStack::getDirtyRegion(int buffer) const
+{
+ Region res;
+ if (uint32_t(buffer) >= NUM_BUFFER_MAX)
+ return res;
+
+ const FlatRegion& reg(dirtyRegion[buffer]);
+ res.set(Rect(reg.rects[0], reg.rects[1], reg.rects[2], reg.rects[3]));
+ return res;
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
+ int surface, int num)
+ : mSharedClient(sharedClient),
+ mSharedStack(sharedClient->surfaces + surface),
+ mNumBuffers(num)
+{
+}
+
+SharedBufferBase::~SharedBufferBase()
+{
+}
+
+uint32_t SharedBufferBase::getIdentity()
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.identity;
+}
+
+size_t SharedBufferBase::getFrontBuffer() const
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return size_t( stack.head );
+}
+
+String8 SharedBufferBase::dump(char const* prefix) const
+{
+ const size_t SIZE = 1024;
+ char buffer[SIZE];
+ String8 result;
+ SharedBufferStack& stack( *mSharedStack );
+ snprintf(buffer, SIZE,
+ "%s[ head=%2d, available=%2d, queued=%2d ] "
+ "reallocMask=%08x, inUse=%2d, identity=%d, status=%d\n",
+ prefix, stack.head, stack.available, stack.queued,
+ stack.reallocMask, stack.inUse, stack.identity, stack.status);
+ result.append(buffer);
+ return result;
+}
+
+
+// ============================================================================
+// conditions and updates
+// ============================================================================
+
+SharedBufferClient::DequeueCondition::DequeueCondition(
+ SharedBufferClient* sbc) : ConditionBase(sbc) {
+}
+bool SharedBufferClient::DequeueCondition::operator()() {
+ return stack.available > 0;
+}
+
+SharedBufferClient::LockCondition::LockCondition(
+ SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
+}
+bool SharedBufferClient::LockCondition::operator()() {
+ return (buf != stack.head ||
+ (stack.queued > 0 && stack.inUse != buf));
+}
+
+SharedBufferServer::ReallocateCondition::ReallocateCondition(
+ SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) {
+}
+bool SharedBufferServer::ReallocateCondition::operator()() {
+ // TODO: we should also check that buf has been dequeued
+ return (buf != stack.head);
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
+ : UpdateBase(sbb) {
+}
+ssize_t SharedBufferClient::QueueUpdate::operator()() {
+ android_atomic_inc(&stack.queued);
+ return NO_ERROR;
+}
+
+SharedBufferClient::UndoDequeueUpdate::UndoDequeueUpdate(SharedBufferBase* sbb)
+ : UpdateBase(sbb) {
+}
+ssize_t SharedBufferClient::UndoDequeueUpdate::operator()() {
+ android_atomic_inc(&stack.available);
+ return NO_ERROR;
+}
+
+SharedBufferServer::UnlockUpdate::UnlockUpdate(
+ SharedBufferBase* sbb, int lockedBuffer)
+ : UpdateBase(sbb), lockedBuffer(lockedBuffer) {
+}
+ssize_t SharedBufferServer::UnlockUpdate::operator()() {
+ if (stack.inUse != lockedBuffer) {
+ LOGE("unlocking %d, but currently locked buffer is %d",
+ lockedBuffer, stack.inUse);
+ return BAD_VALUE;
+ }
+ android_atomic_write(-1, &stack.inUse);
+ return NO_ERROR;
+}
+
+SharedBufferServer::RetireUpdate::RetireUpdate(
+ SharedBufferBase* sbb, int numBuffers)
+ : UpdateBase(sbb), numBuffers(numBuffers) {
+}
+ssize_t SharedBufferServer::RetireUpdate::operator()() {
+ // head is only written in this function, which is single-thread.
+ int32_t head = stack.head;
+
+ // Preventively lock the current buffer before updating queued.
+ android_atomic_write(head, &stack.inUse);
+
+ // Decrement the number of queued buffers
+ int32_t queued;
+ do {
+ queued = stack.queued;
+ if (queued == 0) {
+ return NOT_ENOUGH_DATA;
+ }
+ } while (android_atomic_cmpxchg(queued, queued-1, &stack.queued));
+
+ // update the head pointer
+ head = ((head+1 >= numBuffers) ? 0 : head+1);
+
+ // lock the buffer before advancing head, which automatically unlocks
+ // the buffer we preventively locked upon entering this function
+ android_atomic_write(head, &stack.inUse);
+
+ // advance head
+ android_atomic_write(head, &stack.head);
+
+ // now that head has moved, we can increment the number of available buffers
+ android_atomic_inc(&stack.available);
+ return head;
+}
+
+// ============================================================================
+
+SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
+ int surface, int num)
+ : SharedBufferBase(sharedClient, surface, num), tail(0)
+{
+}
+
+ssize_t SharedBufferClient::dequeue()
+{
+ //LOGD("[%d] about to dequeue a buffer",
+ // mSharedStack->identity);
+ DequeueCondition condition(this);
+ status_t err = waitForCondition(condition);
+ if (err != NO_ERROR)
+ return ssize_t(err);
+
+
+ SharedBufferStack& stack( *mSharedStack );
+ // NOTE: 'stack.available' is part of the conditions, however
+ // decrementing it, never changes any conditions, so we don't need
+ // to do this as part of an update.
+ if (android_atomic_dec(&stack.available) == 0) {
+ LOGW("dequeue probably called from multiple threads!");
+ }
+
+ int dequeued = tail;
+ tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
+ LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail=%d, %s",
+ dequeued, tail, dump("").string());
+ return dequeued;
+}
+
+status_t SharedBufferClient::undoDequeue(int buf)
+{
+ UndoDequeueUpdate update(this);
+ status_t err = updateCondition( update );
+ return err;
+}
+
+status_t SharedBufferClient::lock(int buf)
+{
+ LockCondition condition(this, buf);
+ status_t err = waitForCondition(condition);
+ return err;
+}
+
+status_t SharedBufferClient::queue(int buf)
+{
+ QueueUpdate update(this);
+ status_t err = updateCondition( update );
+ LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
+ return err;
+}
+
+bool SharedBufferClient::needNewBuffer(int buffer) const
+{
+ SharedBufferStack& stack( *mSharedStack );
+ const uint32_t mask = 1<<buffer;
+ return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
+}
+
+status_t SharedBufferClient::setDirtyRegion(int buffer, const Region& reg)
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.setDirtyRegion(buffer, reg);
+}
+
+// ----------------------------------------------------------------------------
+
+SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
+ int surface, int num)
+ : SharedBufferBase(sharedClient, surface, num)
+{
+ mSharedStack->head = num-1;
+ mSharedStack->available = num;
+ mSharedStack->queued = 0;
+ mSharedStack->reallocMask = 0;
+ memset(mSharedStack->dirtyRegion, 0, sizeof(mSharedStack->dirtyRegion));
+}
+
+ssize_t SharedBufferServer::retireAndLock()
+{
+ RetireUpdate update(this, mNumBuffers);
+ ssize_t buf = updateCondition( update );
+ LOGD_IF(DEBUG_ATOMICS, "retire=%d, %s", int(buf), dump("").string());
+ return buf;
+}
+
+status_t SharedBufferServer::unlock(int buffer)
+{
+ UnlockUpdate update(this, buffer);
+ status_t err = updateCondition( update );
+ return err;
+}
+
+status_t SharedBufferServer::reallocate()
+{
+ SharedBufferStack& stack( *mSharedStack );
+ uint32_t mask = (1<<mNumBuffers)-1;
+ android_atomic_or(mask, &stack.reallocMask);
+ return NO_ERROR;
+}
+
+status_t SharedBufferServer::assertReallocate(int buffer)
+{
+ ReallocateCondition condition(this, buffer);
+ status_t err = waitForCondition(condition);
+ return err;
+}
+
+Region SharedBufferServer::getDirtyRegion(int buffer) const
+{
+ SharedBufferStack& stack( *mSharedStack );
+ return stack.getDirtyRegion(buffer);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 474308a..c3fbea2 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -25,6 +25,7 @@
#include <utils/Errors.h>
#include <utils/threads.h>
+#include <utils/CallStack.h>
#include <binder/IPCThreadState.h>
#include <binder/IMemory.h>
#include <utils/Log.h>
@@ -38,102 +39,12 @@
#include <pixelflinger/pixelflinger.h>
-#include <private/ui/SharedState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include <private/ui/SurfaceBuffer.h>
namespace android {
-// ============================================================================
-// SurfaceBuffer
-// ============================================================================
-
-SurfaceBuffer::SurfaceBuffer()
- : BASE(), mOwner(false), mBufferMapper(BufferMapper::get())
-{
- width =
- height =
- stride =
- format =
- usage = 0;
- handle = NULL;
-}
-
-SurfaceBuffer::SurfaceBuffer(const Parcel& data)
- : BASE(), mOwner(true), mBufferMapper(BufferMapper::get())
-{
- // we own the handle in this case
- width = data.readInt32();
- if (width < 0) {
- width = height = stride = format = usage = 0;
- handle = 0;
- } else {
- height = data.readInt32();
- stride = data.readInt32();
- format = data.readInt32();
- usage = data.readInt32();
- handle = data.readNativeHandle();
- }
-}
-
-SurfaceBuffer::~SurfaceBuffer()
-{
- if (handle && mOwner) {
- native_handle_close(handle);
- native_handle_delete(const_cast<native_handle*>(handle));
- }
-}
-
-status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr)
-{
- const Rect lockBounds(width, height);
- status_t res = lock(usage, lockBounds, vaddr);
- return res;
-}
-
-status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
-{
- if (rect.left < 0 || rect.right > this->width ||
- rect.top < 0 || rect.bottom > this->height) {
- LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
- rect.left, rect.top, rect.right, rect.bottom,
- this->width, this->height);
- return BAD_VALUE;
- }
- status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
- return res;
-}
-
-status_t SurfaceBuffer::unlock()
-{
- status_t res = getBufferMapper().unlock(handle);
- return res;
-}
-
-status_t SurfaceBuffer::writeToParcel(Parcel* reply,
- android_native_buffer_t const* buffer)
-{
- if (buffer == NULL)
- return BAD_VALUE;
-
- if (buffer->width < 0 || buffer->height < 0)
- return BAD_VALUE;
-
- status_t err = NO_ERROR;
- if (buffer->handle == NULL) {
- // this buffer doesn't have a handle
- reply->writeInt32(NO_MEMORY);
- } else {
- reply->writeInt32(buffer->width);
- reply->writeInt32(buffer->height);
- reply->writeInt32(buffer->stride);
- reply->writeInt32(buffer->format);
- reply->writeInt32(buffer->usage);
- err = reply->writeNativeHandle(buffer->handle);
- }
- return err;
-}
-
// ----------------------------------------------------------------------
static status_t copyBlt(
@@ -324,7 +235,7 @@ status_t SurfaceControl::setFreezeTint(uint32_t tint) {
return client->setFreezeTint(mToken, tint);
}
-status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
+status_t SurfaceControl::validate(SharedClient const* cblk) const
{
if (mToken<0 || mClient==0) {
LOGE("invalid token (%d, identity=%u) or client (%p)",
@@ -341,9 +252,10 @@ status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const
mToken, mIdentity, err, strerror(-err));
return err;
}
- if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+ uint32_t identity = cblk->getIdentity(mToken);
+ if (mIdentity != identity) {
LOGE("using an invalid surface id=%d, identity=%u should be %d",
- mToken, mIdentity, cblk->layers[mToken].identity);
+ mToken, mIdentity, identity);
return NO_INIT;
}
return NO_ERROR;
@@ -398,14 +310,17 @@ Surface::Surface(const sp<SurfaceControl>& surface)
: mClient(surface->mClient), mSurface(surface->mSurface),
mToken(surface->mToken), mIdentity(surface->mIdentity),
mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(BufferMapper::get()),
+ mBufferMapper(BufferMapper::get()), mSharedBufferClient(NULL),
mWidth(surface->mWidth), mHeight(surface->mHeight)
{
+ mSharedBufferClient = new SharedBufferClient(
+ mClient->mControl, mToken, 2);
+
init();
}
Surface::Surface(const Parcel& parcel)
- : mBufferMapper(BufferMapper::get())
+ : mBufferMapper(BufferMapper::get()), mSharedBufferClient(NULL)
{
sp<IBinder> clientBinder = parcel.readStrongBinder();
mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
@@ -416,9 +331,14 @@ Surface::Surface(const Parcel& parcel)
mFormat = parcel.readInt32();
mFlags = parcel.readInt32();
- if (clientBinder != NULL)
+ // FIXME: what does that mean if clientBinder is NULL here?
+ if (clientBinder != NULL) {
mClient = SurfaceComposerClient::clientForConnection(clientBinder);
+ mSharedBufferClient = new SharedBufferClient(
+ mClient->mControl, mToken, 2);
+ }
+
init();
}
@@ -442,6 +362,7 @@ void Surface::init()
// be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER;
mUsageChanged = true;
+ mNeedFullUpdate = false;
}
Surface::~Surface()
@@ -458,6 +379,7 @@ Surface::~Surface()
// happen without delay, since these resources are quite heavy.
mClient.clear();
mSurface.clear();
+ delete mSharedBufferClient;
IPCThreadState::self()->flushCommands();
}
@@ -473,7 +395,7 @@ bool Surface::isValid() {
return mToken>=0 && mClient!=0;
}
-status_t Surface::validate(per_client_cblk_t const* cblk) const
+status_t Surface::validate(SharedClient const* cblk) const
{
sp<SurfaceComposerClient> client(getClient());
if (mToken<0 || mClient==0) {
@@ -491,9 +413,10 @@ status_t Surface::validate(per_client_cblk_t const* cblk) const
mToken, mIdentity, err, strerror(-err));
return err;
}
- if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+ uint32_t identity = cblk->getIdentity(mToken);
+ if (mIdentity != identity) {
LOGE("using an invalid surface id=%d, identity=%u should be %d",
- mToken, mIdentity, cblk->layers[mToken].identity);
+ mToken, mIdentity, identity);
return NO_INIT;
}
return NO_ERROR;
@@ -511,42 +434,36 @@ bool Surface::isSameSurface(
// ----------------------------------------------------------------------------
-int Surface::setSwapInterval(android_native_window_t* window, int interval)
-{
+int Surface::setSwapInterval(android_native_window_t* window, int interval) {
return 0;
}
int Surface::dequeueBuffer(android_native_window_t* window,
- android_native_buffer_t** buffer)
-{
+ android_native_buffer_t** buffer) {
Surface* self = getSelf(window);
return self->dequeueBuffer(buffer);
}
int Surface::lockBuffer(android_native_window_t* window,
- android_native_buffer_t* buffer)
-{
+ android_native_buffer_t* buffer) {
Surface* self = getSelf(window);
return self->lockBuffer(buffer);
}
int Surface::queueBuffer(android_native_window_t* window,
- android_native_buffer_t* buffer)
-{
+ android_native_buffer_t* buffer) {
Surface* self = getSelf(window);
return self->queueBuffer(buffer);
}
int Surface::query(android_native_window_t* window,
- int what, int* value)
-{
+ int what, int* value) {
Surface* self = getSelf(window);
return self->query(what, value);
}
int Surface::perform(android_native_window_t* window,
- int operation, ...)
-{
+ int operation, ...) {
va_list args;
va_start(args, operation);
Surface* self = getSelf(window);
@@ -557,8 +474,7 @@ int Surface::perform(android_native_window_t* window,
// ----------------------------------------------------------------------------
-status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
-{
+status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer) {
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
if (err == NO_ERROR) {
@@ -567,70 +483,49 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
return err;
}
-status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer)
-{
- return lockBuffer(buffer.get());
-}
-
-status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer)
-{
- return queueBuffer(buffer.get());
-}
-
// ----------------------------------------------------------------------------
+
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
{
- // FIXME: dequeueBuffer() needs proper implementation
-
- Mutex::Autolock _l(mSurfaceLock);
-
sp<SurfaceComposerClient> client(getClient());
- per_client_cblk_t* const cblk = client->mControl;
- status_t err = validate(cblk);
+ status_t err = validate(client->mControl);
if (err != NO_ERROR)
return err;
- SurfaceID index(mToken);
-
- int32_t backIdx = cblk->lock_layer(size_t(index),
- per_client_cblk_t::BLOCKING);
-
- if (backIdx < 0)
- return status_t(backIdx);
-
- mBackbufferIndex = backIdx;
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- volatile const surface_info_t* const back = lcblk->surface + backIdx;
-
- const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
-
- if (backBuffer==0 &&
- !((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged)) {
- LOGW("dequeueBuffer: backbuffer is null, but eNeedNewBuffer "
- "is not set, fetching a buffer anyways...");
+ ssize_t bufIdx = mSharedBufferClient->dequeue();
+ if (bufIdx < 0) {
+ LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
+ return bufIdx;
}
-
- if ((back->flags & surface_info_t::eNeedNewBuffer) ||mUsageChanged ||
- backBuffer==0)
- {
- mUsageChanged = false;
- err = getBufferLocked(backIdx, mUsage);
+
+ // FIXME: in case of failure below, we need to undo the dequeue
+
+ uint32_t usage;
+ const bool usageChanged = getUsage(&usage);
+ const sp<SurfaceBuffer>& backBuffer(mBuffers[bufIdx]);
+ if ((backBuffer == 0) || usageChanged ||
+ mSharedBufferClient->needNewBuffer(bufIdx)) {
+ err = getBufferLocked(bufIdx, usage);
+ LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
+ bufIdx, usage, strerror(-err));
if (err == NO_ERROR) {
// reset the width/height with the what we get from the buffer
- const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
mWidth = uint32_t(backBuffer->width);
mHeight = uint32_t(backBuffer->height);
}
}
+ // if we still don't have a buffer here, we probably ran out of memory
+ if (!err && backBuffer==0) {
+ err = NO_MEMORY;
+ }
+
if (err == NO_ERROR) {
- if (backBuffer != 0) {
- mDirtyRegion.set(backBuffer->width, backBuffer->height);
- *buffer = backBuffer.get();
- } else {
- err = NO_MEMORY;
- }
+ mDirtyRegion.set(backBuffer->width, backBuffer->height);
+ *buffer = backBuffer.get();
+ } else {
+ mSharedBufferClient->undoDequeue(bufIdx);
}
return err;
@@ -638,25 +533,21 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
int Surface::lockBuffer(android_native_buffer_t* buffer)
{
- Mutex::Autolock _l(mSurfaceLock);
-
sp<SurfaceComposerClient> client(getClient());
- per_client_cblk_t* const cblk = client->mControl;
- status_t err = validate(cblk);
+ status_t err = validate(client->mControl);
if (err != NO_ERROR)
return err;
- // FIXME: lockBuffer() needs proper implementation
- return 0;
+ int32_t bufIdx = SurfaceBuffer::getSelf(buffer)->getIndex();
+ err = mSharedBufferClient->lock(bufIdx);
+ LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
+ return err;
}
int Surface::queueBuffer(android_native_buffer_t* buffer)
{
- Mutex::Autolock _l(mSurfaceLock);
-
sp<SurfaceComposerClient> client(getClient());
- per_client_cblk_t* const cblk = client->mControl;
- status_t err = validate(cblk);
+ status_t err = validate(client->mControl);
if (err != NO_ERROR)
return err;
@@ -664,30 +555,30 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
mDirtyRegion.set(mSwapRectangle);
}
- // transmit the dirty region
- SurfaceID index(mToken);
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- _send_dirty_region(lcblk, mDirtyRegion);
+ int32_t bufIdx = SurfaceBuffer::getSelf(buffer)->getIndex();
+ mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
+ err = mSharedBufferClient->queue(bufIdx);
+ LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
- uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
- if (!(newstate & eNextFlipPending))
+ if (err == NO_ERROR) {
+ // FIXME: can we avoid this IPC if we know there is one pending?
client->signalServer();
-
- return NO_ERROR;
+ }
+ return err;
}
int Surface::query(int what, int* value)
{
switch (what) {
- case NATIVE_WINDOW_WIDTH:
- *value = int(mWidth);
- return NO_ERROR;
- case NATIVE_WINDOW_HEIGHT:
- *value = int(mHeight);
- return NO_ERROR;
- case NATIVE_WINDOW_FORMAT:
- *value = int(mFormat);
- return NO_ERROR;
+ case NATIVE_WINDOW_WIDTH:
+ *value = int(mWidth);
+ return NO_ERROR;
+ case NATIVE_WINDOW_HEIGHT:
+ *value = int(mHeight);
+ return NO_ERROR;
+ case NATIVE_WINDOW_FORMAT:
+ *value = int(mFormat);
+ return NO_ERROR;
}
return BAD_VALUE;
}
@@ -715,6 +606,17 @@ void Surface::setUsage(uint32_t reqUsage)
}
}
+bool Surface::getUsage(uint32_t* usage)
+{
+ Mutex::Autolock _l(mSurfaceLock);
+ *usage = mUsage;
+ if (mUsageChanged) {
+ mUsageChanged = false;
+ return true;
+ }
+ return false;
+}
+
// ----------------------------------------------------------------------------
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -723,43 +625,55 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) {
status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
{
+ if (mApiLock.tryLock() != NO_ERROR) {
+ LOGE("calling Surface::lock() from different threads!");
+ CallStack stack;
+ stack.update();
+ stack.dump("Surface::lock called from different threads");
+ return WOULD_BLOCK;
+ }
+
// we're intending to do software rendering from this point
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
sp<SurfaceBuffer> backBuffer;
status_t err = dequeueBuffer(&backBuffer);
+ LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
- err = lockBuffer(backBuffer);
+ err = lockBuffer(backBuffer.get());
+ LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
+ backBuffer->getIndex(), strerror(-err));
if (err == NO_ERROR) {
// we handle copy-back here...
-
+
const Rect bounds(backBuffer->width, backBuffer->height);
Region scratch(bounds);
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
- sp<SurfaceComposerClient> client(getClient());
- per_client_cblk_t* const cblk = client->mControl;
- layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
- volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
- if (back->flags & surface_info_t::eBufferDirty) {
- // content is meaningless in this case and the whole surface
- // needs to be redrawn.
+ if (mNeedFullUpdate) {
+ // reset newDirtyRegion to bounds when a buffer is reallocated
+ // it would be better if this information was associated with
+ // the buffer and made available to outside of Surface.
+ // This will do for now though.
+ mNeedFullUpdate = false;
newDirtyRegion.set(bounds);
} else {
newDirtyRegion.andSelf(bounds);
- const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
- if (frontBuffer !=0 &&
- backBuffer->width == frontBuffer->width &&
- backBuffer->height == frontBuffer->height &&
- !(lcblk->flags & eNoCopyBack))
- {
- const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
- if (!copyback.isEmpty() && frontBuffer!=0) {
- // copy front to back
- copyBlt(backBuffer, frontBuffer, copyback);
- }
+ }
+
+ const sp<SurfaceBuffer>& frontBuffer(mPostedBuffer);
+ if (frontBuffer !=0 &&
+ backBuffer->width == frontBuffer->width &&
+ backBuffer->height == frontBuffer->height &&
+ !(mFlags & ISurfaceComposer::eDestroyBackbuffer))
+ {
+ const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+ if (!copyback.isEmpty() && frontBuffer!=0) {
+ // copy front to back
+ copyBlt(backBuffer, frontBuffer, copyback);
}
}
+
mDirtyRegion = newDirtyRegion;
mOldDirtyRegion = newDirtyRegion;
@@ -768,8 +682,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
newDirtyRegion.bounds(), &vaddr);
- LOGW_IF(res, "failed locking buffer %d (%p)",
- mBackbufferIndex, backBuffer->handle);
+ LOGW_IF(res, "failed locking buffer (handle = %p)",
+ backBuffer->handle);
mLockedBuffer = backBuffer;
other->w = backBuffer->width;
@@ -780,36 +694,29 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
other->bits = vaddr;
}
}
+ mApiLock.unlock();
return err;
}
status_t Surface::unlockAndPost()
{
- if (mLockedBuffer == 0)
+ if (mLockedBuffer == 0) {
+ LOGE("unlockAndPost failed, no locked buffer");
return BAD_VALUE;
+ }
- status_t res = mLockedBuffer->unlock();
- LOGW_IF(res, "failed unlocking buffer %d (%p)",
- mBackbufferIndex, mLockedBuffer->handle);
+ status_t err = mLockedBuffer->unlock();
+ LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
- status_t err = queueBuffer(mLockedBuffer);
+ err = queueBuffer(mLockedBuffer.get());
+ LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
+ mLockedBuffer->getIndex(), strerror(-err));
+
+ mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
-void Surface::_send_dirty_region(
- layer_cblk_t* lcblk, const Region& dirty)
-{
- const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
- flat_region_t* flat_region = lcblk->region + index;
- status_t err = dirty.write(flat_region, sizeof(flat_region_t));
- if (err < NO_ERROR) {
- // region doesn't fit, use the bounds
- const Region reg(dirty.bounds());
- reg.write(flat_region, sizeof(flat_region_t));
- }
-}
-
void Surface::setSwapRectangle(const Rect& r) {
Mutex::Autolock _l(mSurfaceLock);
mSwapRectangle = r;
@@ -829,15 +736,22 @@ status_t Surface::getBufferLocked(int index, int usage)
currentBuffer.clear();
}
- sp<SurfaceBuffer> buffer = s->getBuffer(usage);
- LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
+ sp<SurfaceBuffer> buffer = s->requestBuffer(index, usage);
+ LOGE_IF(buffer==0,
+ "ISurface::getBuffer(%d, %08x) returned NULL",
+ index, usage);
if (buffer != 0) { // this should never happen by construction
+ LOGE_IF(buffer->handle == NULL,
+ "requestBuffer(%d, %08x) returned a buffer with a null handle",
+ index, usage);
if (buffer->handle != NULL) {
err = getBufferMapper().registerBuffer(buffer->handle);
LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
err, strerror(-err));
if (err == NO_ERROR) {
currentBuffer = buffer;
+ currentBuffer->setIndex(index);
+ mNeedFullUpdate = true;
}
}
}
diff --git a/libs/ui/SurfaceBuffer.cpp b/libs/ui/SurfaceBuffer.cpp
new file mode 100644
index 0000000..0510bc1
--- /dev/null
+++ b/libs/ui/SurfaceBuffer.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#define LOG_TAG "SurfaceBuffer"
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+
+#include <ui/BufferMapper.h>
+#include <ui/Rect.h>
+#include <private/ui/SurfaceBuffer.h>
+
+namespace android {
+
+// ============================================================================
+// SurfaceBuffer
+// ============================================================================
+
+SurfaceBuffer::SurfaceBuffer()
+ : BASE(), mOwner(false), mBufferMapper(BufferMapper::get()), mIndex(-1)
+{
+ width =
+ height =
+ stride =
+ format =
+ usage = 0;
+ handle = NULL;
+}
+
+SurfaceBuffer::SurfaceBuffer(const Parcel& data)
+ : BASE(), mOwner(true), mBufferMapper(BufferMapper::get())
+{
+ // we own the handle in this case
+ width = data.readInt32();
+ if (width < 0) {
+ width = height = stride = format = usage = 0;
+ handle = 0;
+ } else {
+ height = data.readInt32();
+ stride = data.readInt32();
+ format = data.readInt32();
+ usage = data.readInt32();
+ handle = data.readNativeHandle();
+ }
+}
+
+SurfaceBuffer::~SurfaceBuffer()
+{
+ if (handle && mOwner) {
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle*>(handle));
+ }
+}
+
+status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr)
+{
+ const Rect lockBounds(width, height);
+ status_t res = lock(usage, lockBounds, vaddr);
+ return res;
+}
+
+status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
+{
+ if (rect.left < 0 || rect.right > this->width ||
+ rect.top < 0 || rect.bottom > this->height) {
+ LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
+ rect.left, rect.top, rect.right, rect.bottom,
+ this->width, this->height);
+ return BAD_VALUE;
+ }
+ status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
+ return res;
+}
+
+status_t SurfaceBuffer::unlock()
+{
+ status_t res = getBufferMapper().unlock(handle);
+ return res;
+}
+
+status_t SurfaceBuffer::writeToParcel(Parcel* reply,
+ android_native_buffer_t const* buffer)
+{
+ if (buffer == NULL)
+ return BAD_VALUE;
+
+ if (buffer->width < 0 || buffer->height < 0)
+ return BAD_VALUE;
+
+ status_t err = NO_ERROR;
+ if (buffer->handle == NULL) {
+ // this buffer doesn't have a handle
+ reply->writeInt32(NO_MEMORY);
+ } else {
+ reply->writeInt32(buffer->width);
+ reply->writeInt32(buffer->height);
+ reply->writeInt32(buffer->stride);
+ reply->writeInt32(buffer->format);
+ reply->writeInt32(buffer->usage);
+ err = reply->writeNativeHandle(buffer->handle);
+ }
+ return err;
+}
+
+
+void SurfaceBuffer::setIndex(int index) {
+ mIndex = index;
+}
+
+int SurfaceBuffer::getIndex() const {
+ return mIndex;
+}
+
+
+}; // namespace android
+
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index d2cef78..8401cb6 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -40,8 +40,8 @@
#include <ui/SurfaceComposerClient.h>
#include <ui/Rect.h>
-#include <private/ui/SharedState.h>
#include <private/ui/LayerState.h>
+#include <private/ui/SharedBufferStack.h>
#include <private/ui/SurfaceFlingerSynchro.h>
#define VERBOSE(...) ((void)0)
@@ -103,169 +103,6 @@ static volatile surface_flinger_cblk_t const * get_cblk()
// ---------------------------------------------------------------------------
-// these functions are used by the clients
-status_t per_client_cblk_t::validate(size_t i) const {
- if (uint32_t(i) >= NUM_LAYERS_MAX)
- return BAD_INDEX;
- if (layers[i].swapState & eInvalidSurface)
- return NO_MEMORY;
- return NO_ERROR;
-}
-
-int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags)
-{
- int32_t index;
- uint32_t state;
- int timeout = 0;
- status_t result;
- layer_cblk_t * const layer = layers + i;
- const bool blocking = flags & BLOCKING;
- const bool inspect = flags & INSPECT;
-
- do {
- state = layer->swapState;
-
- if (UNLIKELY((state&(eFlipRequested|eNextFlipPending)) == eNextFlipPending)) {
- LOGE("eNextFlipPending set but eFlipRequested not set, "
- "layer=%d (lcblk=%p), state=%08x",
- int(i), layer, int(state));
- return INVALID_OPERATION;
- }
-
- if (UNLIKELY(state&eLocked)) {
- LOGE("eLocked set when entering lock_layer(), "
- "layer=%d (lcblk=%p), state=%08x",
- int(i), layer, int(state));
- return WOULD_BLOCK;
- }
-
-
- if (state & (eFlipRequested | eNextFlipPending | eResizeRequested
- | eInvalidSurface))
- {
- int32_t resizeIndex;
- Mutex::Autolock _l(lock);
- // might block for a very short amount of time
- // will never cause the server to block (trylock())
-
- goto start_loop_here;
-
- // We block the client if:
- // eNextFlipPending: we've used both buffers already, so we need to
- // wait for one to become availlable.
- // eResizeRequested: the buffer we're going to acquire is being
- // resized. Block until it is done.
- // eFlipRequested && eBusy: the buffer we're going to acquire is
- // currently in use by the server.
- // eInvalidSurface: this is a special case, we don't block in this
- // case, we just return an error.
-
- while((state & (eNextFlipPending|eInvalidSurface)) ||
- (state & ((resizeIndex) ? eResizeBuffer1 : eResizeBuffer0)) ||
- ((state & (eFlipRequested|eBusy)) == (eFlipRequested|eBusy)) )
- {
- if (state & eInvalidSurface)
- return NO_MEMORY;
-
- if (!blocking)
- return WOULD_BLOCK;
-
- timeout = 0;
- result = cv.waitRelative(lock, seconds(1));
- if (__builtin_expect(result!=NO_ERROR, false)) {
- const int newState = layer->swapState;
- LOGW( "lock_layer timed out (is the CPU pegged?) "
- "layer=%d, lcblk=%p, state=%08x (was %08x)",
- int(i), layer, newState, int(state));
- timeout = newState != int(state);
- }
-
- start_loop_here:
- state = layer->swapState;
- resizeIndex = (state&eIndex) ^ ((state&eFlipRequested)>>1);
- }
-
- LOGW_IF(timeout,
- "lock_layer() timed out but didn't appear to need "
- "to be locked and we recovered "
- "(layer=%d, lcblk=%p, state=%08x)",
- int(i), layer, int(state));
- }
-
- // eFlipRequested is not set and cannot be set by another thread: it's
- // safe to use the first buffer without synchronization.
-
- // Choose the index depending on eFlipRequested.
- // When it's set, choose the 'other' buffer.
- index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
-
- // make sure this buffer is valid
- status_t err = layer->surface[index].status;
- if (err < 0) {
- return err;
- }
-
- if (inspect) {
- // we just want to inspect this layer. don't lock it.
- goto done;
- }
-
- // last thing before we're done, we need to atomically lock the state
- } while (android_atomic_cmpxchg(state, state|eLocked, &(layer->swapState)));
-
- VERBOSE("locked layer=%d (lcblk=%p), buffer=%d, state=0x%08x",
- int(i), layer, int(index), int(state));
-
- // store the index of the locked buffer (for client use only)
- layer->flags &= ~eBufferIndex;
- layer->flags |= ((index << eBufferIndexShift) & eBufferIndex);
-
-done:
- return index;
-}
-
-uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
-{
- // atomically set eFlipRequested and clear eLocked and optionally
- // set eNextFlipPending if eFlipRequested was already set
-
- layer_cblk_t * const layer = layers + i;
- int32_t oldvalue, newvalue;
- do {
- oldvalue = layer->swapState;
- // get current value
-
- newvalue = oldvalue & ~eLocked;
- // clear eLocked
-
- newvalue |= eFlipRequested;
- // set eFlipRequested
-
- if (oldvalue & eFlipRequested)
- newvalue |= eNextFlipPending;
- // if eFlipRequested was already set, set eNextFlipPending
-
- } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
-
- VERBOSE("request pageflip for layer=%d, buffer=%d, state=0x%08x",
- int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
- int(newvalue));
-
- // from this point, the server can kick in at any time and use the first
- // buffer, so we cannot use it anymore, and we must use the 'other'
- // buffer instead (or wait if it is not available yet, see lock_layer).
-
- return newvalue;
-}
-
-void per_client_cblk_t::unlock_layer(size_t i)
-{
- layer_cblk_t * const layer = layers + i;
- android_atomic_and(~eLocked, &layer->swapState);
-}
-
-// ---------------------------------------------------------------------------
-
static inline int compare_type( const layer_state_t& lhs,
const layer_state_t& rhs) {
if (lhs.surface < rhs.surface) return -1;
@@ -315,7 +152,7 @@ void SurfaceComposerClient::_init(
mControlMemory = mClient->getControlBlock();
mSignalServer = new SurfaceFlingerSynchro(sm);
- mControl = static_cast<per_client_cblk_t *>(mControlMemory->getBase());
+ mControl = static_cast<SharedClient *>(mControlMemory->getBase());
}
SurfaceComposerClient::~SurfaceComposerClient()
@@ -539,18 +376,17 @@ void SurfaceComposerClient::closeGlobalTransaction()
const size_t N = clients.size();
VERBOSE("closeGlobalTransaction (%ld clients)", N);
- if (N == 1) {
- clients[0]->closeTransaction();
- } else {
- const sp<ISurfaceComposer>& sm(_get_surface_manager());
- sm->openGlobalTransaction();
- for (size_t i=0; i<N; i++) {
- clients[i]->closeTransaction();
- }
- sm->closeGlobalTransaction();
+
+ const sp<ISurfaceComposer>& sm(_get_surface_manager());
+ sm->openGlobalTransaction();
+ for (size_t i=0; i<N; i++) {
+ clients[i]->closeTransaction();
}
+ sm->closeGlobalTransaction();
+
}
+
status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
{
const sp<ISurfaceComposer>& sm(_get_surface_manager());