summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2011-04-20 14:20:59 -0700
committerMathias Agopian <mathias@google.com>2011-06-13 15:51:35 -0700
commit7bb843ca0777111dae7daf8f1b0705817cf523c4 (patch)
tree10545edc3ce21f38282d5e67e5bc08ff729884b3
parentdfc7958a2eafba52db90743a4707eed1d780b63b (diff)
downloadframeworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.zip
frameworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.tar.gz
frameworks_base-7bb843ca0777111dae7daf8f1b0705817cf523c4.tar.bz2
unify SurfaceTexture and Surface
Add the concept of synchronous dequeueBuffer in SurfaceTexture Implement {Surface|SurfaceTextureClient}::setSwapInterval() Add SurfaceTexture logging fix onFrameAvailable
-rw-r--r--cmds/bootanimation/BootAnimation.cpp3
-rw-r--r--include/private/surfaceflinger/SharedBufferStack.h348
-rw-r--r--include/surfaceflinger/IGraphicBufferAlloc.h2
-rw-r--r--include/surfaceflinger/ISurface.h25
-rw-r--r--include/surfaceflinger/ISurfaceComposer.h13
-rw-r--r--include/surfaceflinger/ISurfaceComposerClient.h6
-rw-r--r--include/surfaceflinger/Surface.h73
-rw-r--r--include/surfaceflinger/SurfaceComposerClient.h6
-rw-r--r--libs/gui/Android.mk1
-rw-r--r--libs/gui/ISurface.cpp47
-rw-r--r--libs/gui/ISurfaceComposer.cpp25
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp56
-rw-r--r--libs/gui/SharedBufferStack.cpp714
-rw-r--r--libs/gui/Surface.cpp634
-rw-r--r--libs/gui/SurfaceComposerClient.cpp17
-rw-r--r--libs/gui/SurfaceTextureClient.cpp6
-rw-r--r--services/surfaceflinger/Android.mk22
-rw-r--r--services/surfaceflinger/Layer.cpp866
-rw-r--r--services/surfaceflinger/Layer.h164
-rw-r--r--services/surfaceflinger/LayerBase.cpp208
-rw-r--r--services/surfaceflinger/LayerBase.h84
-rw-r--r--services/surfaceflinger/LayerDim.cpp2
-rw-r--r--services/surfaceflinger/LayerDim.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp214
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h42
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp76
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.h55
-rw-r--r--services/surfaceflinger/clz.h10
28 files changed, 600 insertions, 3121 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 69c4597..0acba8b 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -313,9 +313,6 @@ bool BootAnimation::android()
const GLint yc = (mHeight - mAndroid[0].h) / 2;
const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
- // draw and update only what we need
- mFlingerSurface->setSwapRectangle(updateRect);
-
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
updateRect.height());
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 717f837..0da03d1 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -20,355 +20,12 @@
#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.
- *
- */
-
-// ----------------------------------------------------------------------------
-
-class Region;
-class SharedBufferStack;
-class SharedClient;
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferStack
-{
- friend class SharedClient;
- friend class SharedBufferBase;
- friend class SharedBufferClient;
- friend class SharedBufferServer;
-
-public:
- // When changing these values, the COMPILE_TIME_ASSERT at the end of this
- // file need to be updated.
- static const unsigned int NUM_LAYERS_MAX = 31;
- static const unsigned int NUM_BUFFER_MAX = 32;
- static const unsigned int NUM_BUFFER_MIN = 2;
- static const unsigned int NUM_DISPLAY_MAX = 4;
-
- struct Statistics { // 4 longs
- typedef int32_t usecs_t;
- usecs_t totalTime;
- usecs_t reserved[3];
- };
-
- struct SmallRect {
- uint16_t l, t, r, b;
- };
-
- struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
- static const unsigned int NUM_RECT_MAX = 5;
- uint32_t count;
- SmallRect rects[NUM_RECT_MAX];
- };
-
- struct BufferData {
- FlatRegion dirtyRegion;
- SmallRect crop;
- uint8_t transform;
- uint8_t reserved[3];
- };
-
- SharedBufferStack();
- void init(int32_t identity);
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint8_t transform);
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(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 reserved1;
- volatile status_t status; // surface's status code
-
- // not part of the conditions
- volatile int32_t reallocMask;
- volatile int8_t index[NUM_BUFFER_MAX];
-
- int32_t identity; // surface's identity (const)
- int32_t token; // surface's token (for debugging)
- Statistics stats;
- int8_t headBuf; // last retired buffer
- uint8_t reservedBytes[3];
- int32_t reserved;
- BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
-};
-
-// ----------------------------------------------------------------------------
-
-// 64 KB max
-class SharedClient
-{
-public:
- SharedClient();
- ~SharedClient();
- status_t validate(size_t token) const;
-
-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[ SharedBufferStack::NUM_LAYERS_MAX ];
-};
-
-// ============================================================================
-
-class SharedBufferBase
-{
-public:
- SharedBufferBase(SharedClient* sharedClient, int surface,
- int32_t identity);
- ~SharedBufferBase();
- status_t getStatus() const;
- int32_t getIdentity() const;
- String8 dump(char const* prefix) const;
-
-protected:
- SharedClient* const mSharedClient;
- SharedBufferStack* const mSharedStack;
- const int mIdentity;
-
- friend struct Update;
- friend struct QueueUpdate;
-
- struct ConditionBase {
- SharedBufferStack& stack;
- inline ConditionBase(SharedBufferBase* sbc)
- : stack(*sbc->mSharedStack) { }
- virtual ~ConditionBase() { };
- virtual bool operator()() const = 0;
- virtual const char* name() const = 0;
- };
- status_t waitForCondition(const ConditionBase& condition);
-
- struct UpdateBase {
- SharedBufferStack& stack;
- inline UpdateBase(SharedBufferBase* sbb)
- : stack(*sbb->mSharedStack) { }
- };
- template <typename T>
- status_t updateCondition(T update);
-};
-
-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,
- int32_t identity);
-
- ssize_t dequeue();
- status_t undoDequeue(int buf);
-
- status_t lock(int buf);
- status_t cancel(int buf);
- status_t queue(int buf);
- bool needNewBuffer(int buffer) const;
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint32_t transform);
-
- class SetBufferCountCallback {
- friend class SharedBufferClient;
- virtual status_t operator()(int bufferCount) const = 0;
- protected:
- virtual ~SetBufferCountCallback() { }
- };
- status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
-
-private:
- friend struct Condition;
- friend struct DequeueCondition;
- friend struct LockCondition;
-
- struct QueueUpdate : public UpdateBase {
- inline QueueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct DequeueUpdate : public UpdateBase {
- inline DequeueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct CancelUpdate : public UpdateBase {
- int tail, buf;
- inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
- inline ssize_t operator()();
- };
-
- // --
-
- struct DequeueCondition : public ConditionBase {
- inline DequeueCondition(SharedBufferClient* sbc);
- inline bool operator()() const;
- inline const char* name() const { return "DequeueCondition"; }
- };
-
- struct LockCondition : public ConditionBase {
- int buf;
- inline LockCondition(SharedBufferClient* sbc, int buf);
- inline bool operator()() const;
- inline const char* name() const { return "LockCondition"; }
- };
-
- int32_t computeTail() const;
-
- mutable RWLock mLock;
- int mNumBuffers;
-
- int32_t tail;
- int32_t queued_head;
- // statistics...
- nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
-};
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferServer
- : public SharedBufferBase,
- public LightRefBase<SharedBufferServer>
-{
-public:
- SharedBufferServer(SharedClient* sharedClient, int surface, int num,
- int32_t identity);
-
- ssize_t retireAndLock();
- void setStatus(status_t status);
- status_t reallocateAll();
- status_t reallocateAllExcept(int buffer);
- int32_t getQueuedCount() const;
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(int buffer) const;
-
- status_t resize(int newNumBuffers);
- status_t grow(int newNumBuffers);
- status_t shrink(int newNumBuffers);
-
- SharedBufferStack::Statistics getStats() const;
-
-
-private:
- friend class LightRefBase<SharedBufferServer>;
- ~SharedBufferServer();
-
- /*
- * BufferList is basically a fixed-capacity sorted-vector of
- * unsigned 5-bits ints using a 32-bits int as storage.
- * it has efficient iterators to find items in the list and not in the list.
- */
- class BufferList {
- size_t mCapacity;
- uint32_t mList;
- public:
- BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
- : mCapacity(c), mList(0) { }
- status_t add(int value);
- status_t remove(int value);
- uint32_t getMask() const { return mList; }
-
- class const_iterator {
- friend class BufferList;
- uint32_t mask, curr;
- const_iterator(uint32_t mask) :
- mask(mask), curr(__builtin_clz(mask)) {
- }
- public:
- inline bool operator == (const const_iterator& rhs) const {
- return mask == rhs.mask;
- }
- inline bool operator != (const const_iterator& rhs) const {
- return mask != rhs.mask;
- }
- inline int operator *() const { return curr; }
- inline const const_iterator& operator ++() {
- mask &= ~(1<<(31-curr));
- curr = __builtin_clz(mask);
- return *this;
- }
- };
-
- inline const_iterator begin() const {
- return const_iterator(mList);
- }
- inline const_iterator end() const {
- return const_iterator(0);
- }
- inline const_iterator free_begin() const {
- uint32_t mask = (1 << (32-mCapacity)) - 1;
- return const_iterator( ~(mList | mask) );
- }
- };
-
- // this protects mNumBuffers and mBufferList
- mutable RWLock mLock;
- int mNumBuffers;
- BufferList mBufferList;
-
- struct BuffersAvailableCondition : public ConditionBase {
- int mNumBuffers;
- inline BuffersAvailableCondition(SharedBufferServer* sbs,
- int numBuffers);
- inline bool operator()() const;
- inline const char* name() const { return "BuffersAvailableCondition"; }
- };
-
- struct RetireUpdate : public UpdateBase {
- const int numBuffers;
- inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
- inline ssize_t operator()();
- };
-
- struct StatusUpdate : public UpdateBase {
- const status_t status;
- inline StatusUpdate(SharedBufferBase* sbb, status_t status);
- inline ssize_t operator()();
- };
-};
-
-// ===========================================================================
+#define NUM_DISPLAY_MAX 4
struct display_cblk_t
{
@@ -389,12 +46,11 @@ struct surface_flinger_cblk_t // 4KB max
uint8_t connected;
uint8_t reserved[3];
uint32_t pad[7];
- display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
+ display_cblk_t displays[NUM_DISPLAY_MAX];
};
// ---------------------------------------------------------------------------
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 65536)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
// ---------------------------------------------------------------------------
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
index 01e4bd9..e1b6b57 100644
--- a/include/surfaceflinger/IGraphicBufferAlloc.h
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -27,6 +27,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class GraphicBuffer;
+
class IGraphicBufferAlloc : public IInterface
{
public:
diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h
index cd0ee40..5fdf234 100644
--- a/include/surfaceflinger/ISurface.h
+++ b/include/surfaceflinger/ISurface.h
@@ -27,42 +27,23 @@
#include <ui/PixelFormat.h>
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-
namespace android {
typedef int32_t SurfaceID;
-class GraphicBuffer;
+class ISurfaceTexture;
class ISurface : public IInterface
{
protected:
enum {
- RESERVED0 = IBinder::FIRST_CALL_TRANSACTION,
- RESERVED1,
- RESERVED2,
- REQUEST_BUFFER,
- SET_BUFFER_COUNT,
+ GET_SURFACE_TEXTURE = IBinder::FIRST_CALL_TRANSACTION,
};
public:
DECLARE_META_INTERFACE(Surface);
- /*
- * requests a new buffer for the given index. If w, h, or format are
- * null the buffer is created with the parameters assigned to the
- * surface it is bound to. Otherwise the buffer's parameters are
- * set to those specified.
- */
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
-
- /*
- * sets the number of buffers dequeuable for this surface.
- */
- virtual status_t setBufferCount(int bufferCount) = 0;
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index dea1b10..03fd01b 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -33,6 +33,8 @@
namespace android {
// ----------------------------------------------------------------------------
+class IMemoryHeap;
+
class ISurfaceComposer : public IInterface
{
public:
@@ -95,10 +97,6 @@ public:
*/
virtual sp<ISurfaceComposerClient> createConnection() = 0;
- /* create a client connection with surface flinger
- */
- virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
-
/* create a graphic buffer allocator
*/
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
@@ -134,11 +132,6 @@ public:
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
virtual status_t turnElectronBeamOn(int32_t mode) = 0;
- /* Signal surfaceflinger that there might be some work to do
- * This is an ASYNCHRONOUS call.
- */
- virtual void signal() const = 0;
-
/* verify that an ISurface was created by SurfaceFlinger.
*/
virtual bool authenticateSurface(const sp<ISurface>& surface) const = 0;
@@ -154,7 +147,6 @@ public:
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
- CREATE_CLIENT_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
GET_CBLK,
OPEN_GLOBAL_TRANSACTION,
@@ -162,7 +154,6 @@ public:
SET_ORIENTATION,
FREEZE_DISPLAY,
UNFREEZE_DISPLAY,
- SIGNAL,
CAPTURE_SCREEN,
TURN_ELECTRON_BEAM_OFF,
TURN_ELECTRON_BEAM_ON,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 46b1bb7..2e75a0e 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -33,9 +33,6 @@ namespace android {
// ----------------------------------------------------------------------------
-class IMemoryHeap;
-
-typedef int32_t ClientID;
typedef int32_t DisplayID;
// ----------------------------------------------------------------------------
@@ -57,9 +54,6 @@ public:
status_t writeToParcel(Parcel* parcel) const;
};
- virtual sp<IMemoryHeap> getControlBlock() const = 0;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const = 0;
-
/*
* Requires ACCESS_SURFACE_FLINGER permission
*/
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index ab30f45..8845dc9 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -43,9 +43,7 @@ class IOMX;
class Rect;
class Surface;
class SurfaceComposerClient;
-class SharedClient;
-class SharedBufferClient;
-class SurfaceClient;
+class SurfaceTextureClient;
// ---------------------------------------------------------------------------
@@ -162,9 +160,6 @@ public:
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
status_t unlockAndPost();
- // setSwapRectangle() is intended to be used by GL ES clients
- void setSwapRectangle(const Rect& r);
-
sp<IBinder> asBinder() const;
private:
@@ -209,6 +204,7 @@ private:
static int query(const ANativeWindow* window, int what, int* value);
static int perform(ANativeWindow* window, int operation, ...);
+ int setSwapInterval(int interval);
int dequeueBuffer(ANativeWindowBuffer** buffer);
int lockBuffer(ANativeWindowBuffer* buffer);
int queueBuffer(ANativeWindowBuffer* buffer);
@@ -216,83 +212,23 @@ private:
int query(int what, int* value) const;
int perform(int operation, va_list args);
- void dispatch_setUsage(va_list args);
- int dispatch_connect(va_list args);
- int dispatch_disconnect(va_list args);
- int dispatch_crop(va_list args);
- int dispatch_set_buffer_count(va_list args);
- int dispatch_set_buffers_geometry(va_list args);
- int dispatch_set_buffers_transform(va_list args);
- int dispatch_set_buffers_timestamp(va_list args);
-
- void setUsage(uint32_t reqUsage);
- int connect(int api);
- int disconnect(int api);
- int crop(Rect const* rect);
- int setBufferCount(int bufferCount);
- int setBuffersGeometry(int w, int h, int format);
- int setBuffersTransform(int transform);
- int setBuffersTimestamp(int64_t timestamp);
-
/*
* private stuff...
*/
void init();
status_t validate(bool inCancelBuffer = false) const;
- // When the buffer pool is a fixed size we want to make sure SurfaceFlinger
- // won't stall clients, so we require an extra buffer.
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
-
- inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
- inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
-
- status_t getBufferLocked(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
-
int getConnectedApi() const;
- bool needNewBuffer(int bufIdx,
- uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const;
-
static void cleanCachedSurfacesLocked();
- class BufferInfo {
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mFormat;
- uint32_t mUsage;
- mutable uint32_t mDirty;
- enum {
- GEOMETRY = 0x01
- };
- public:
- BufferInfo();
- void set(uint32_t w, uint32_t h, uint32_t format);
- void set(uint32_t usage);
- void get(uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const;
- bool validateBuffer(const sp<GraphicBuffer>& buffer) const;
- };
-
// constants
- GraphicBufferMapper& mBufferMapper;
- SurfaceClient& mClient;
- SharedBufferClient* mSharedBufferClient;
status_t mInitCheck;
sp<ISurface> mSurface;
+ sp<SurfaceTextureClient> mSurfaceTextureClient;
uint32_t mIdentity;
PixelFormat mFormat;
uint32_t mFlags;
-
- // protected by mSurfaceLock
- Rect mSwapRectangle;
- int mConnected;
- Rect mNextBufferCrop;
- uint32_t mNextBufferTransform;
- BufferInfo mBufferInfo;
// protected by mSurfaceLock. These are also used from lock/unlock
// but in that case, they must be called form the same thread.
@@ -304,9 +240,6 @@ private:
mutable Region mOldDirtyRegion;
bool mReserved;
- // only used from dequeueBuffer()
- Vector< sp<GraphicBuffer> > mBuffers;
-
// query() must be called from dequeueBuffer() thread
uint32_t mWidth;
uint32_t mHeight;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index c61a5bf..140b9f8 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -36,10 +36,10 @@ namespace android {
// ---------------------------------------------------------------------------
-class Region;
-class SharedClient;
-class ISurfaceComposer;
class DisplayInfo;
+class IMemoryHeap;
+class ISurfaceComposer;
+class Region;
class surface_flinger_cblk_t;
// ---------------------------------------------------------------------------
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index b5737ff..4070eba 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -16,7 +16,6 @@ LOCAL_SRC_FILES:= \
ISurfaceComposerClient.cpp \
IGraphicBufferAlloc.cpp \
LayerState.cpp \
- SharedBufferStack.cpp \
Surface.cpp \
SurfaceComposerClient.cpp \
diff --git a/libs/gui/ISurface.cpp b/libs/gui/ISurface.cpp
index 23b90af..96155d7 100644
--- a/libs/gui/ISurface.cpp
+++ b/libs/gui/ISurface.cpp
@@ -22,9 +22,7 @@
#include <binder/Parcel.h>
-#include <ui/GraphicBuffer.h>
-
-#include <surfaceflinger/Surface.h>
+#include <gui/ISurfaceTexture.h>
#include <surfaceflinger/ISurface.h>
namespace android {
@@ -39,30 +37,11 @@ public:
{
}
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
- {
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const {
Parcel data, reply;
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
- data.writeInt32(bufferIdx);
- data.writeInt32(w);
- data.writeInt32(h);
- data.writeInt32(format);
- data.writeInt32(usage);
- remote()->transact(REQUEST_BUFFER, data, &reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
- reply.read(*buffer);
- return buffer;
- }
-
- virtual status_t setBufferCount(int bufferCount)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- remote()->transact(SET_BUFFER_COUNT, data, &reply);
- status_t err = reply.readInt32();
- return err;
+ remote()->transact(GET_SURFACE_TEXTURE, data, &reply);
+ return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
}
};
@@ -74,23 +53,9 @@ status_t BnSurface::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
- case REQUEST_BUFFER: {
- CHECK_INTERFACE(ISurface, data, reply);
- int bufferIdx = data.readInt32();
- uint32_t w = data.readInt32();
- uint32_t h = data.readInt32();
- uint32_t format = data.readInt32();
- uint32_t usage = data.readInt32();
- sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format, usage));
- if (buffer == NULL)
- return BAD_VALUE;
- return reply->write(*buffer);
- }
- case SET_BUFFER_COUNT: {
+ case GET_SURFACE_TEXTURE: {
CHECK_INTERFACE(ISurface, data, reply);
- int bufferCount = data.readInt32();
- status_t err = setBufferCount(bufferCount);
- reply->writeInt32(err);
+ reply->writeStrongBinder( getSurfaceTexture()->asBinder() );
return NO_ERROR;
}
default:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8951c3f..40450a3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -57,15 +57,6 @@ public:
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual sp<ISurfaceComposerClient> createClientConnection()
- {
- uint32_t n;
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CREATE_CLIENT_CONNECTION, data, &reply);
- return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
- }
-
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
{
uint32_t n;
@@ -174,13 +165,6 @@ public:
return reply.readInt32();
}
- virtual void signal() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::SIGNAL, data, &reply, IBinder::FLAG_ONEWAY);
- }
-
virtual bool authenticateSurface(const sp<ISurface>& surface) const
{
Parcel data, reply;
@@ -229,11 +213,6 @@ status_t BnSurfaceComposer::onTransact(
sp<IBinder> b = createConnection()->asBinder();
reply->writeStrongBinder(b);
} break;
- case CREATE_CLIENT_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = createClientConnection()->asBinder();
- reply->writeStrongBinder(b);
- } break;
case CREATE_GRAPHIC_BUFFER_ALLOC: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
@@ -270,10 +249,6 @@ status_t BnSurfaceComposer::onTransact(
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bootFinished();
} break;
- case SIGNAL: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- signal();
- } break;
case GET_CBLK: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> b = getCblk()->asBinder();
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index ea38e08..8d83392 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -50,9 +50,7 @@
namespace android {
enum {
- GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
- GET_TOKEN,
- CREATE_SURFACE,
+ CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
DESTROY_SURFACE,
SET_STATE
};
@@ -65,23 +63,6 @@ public:
{
}
- virtual sp<IMemoryHeap> getControlBlock() const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- remote()->transact(GET_CBLK, data, &reply);
- return interface_cast<IMemoryHeap>(reply.readStrongBinder());
- }
-
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- data.writeStrongBinder(sur->asBinder());
- remote()->transact(GET_TOKEN, data, &reply);
- return reply.readInt32();
- }
-
virtual sp<ISurface> createSurface( surface_data_t* params,
const String8& name,
DisplayID display,
@@ -131,41 +112,6 @@ IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClie
status_t BnSurfaceComposerClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- // codes that don't require permission check
-
- switch(code) {
- case GET_CBLK: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- sp<IMemoryHeap> ctl(getControlBlock());
- reply->writeStrongBinder(ctl->asBinder());
- return NO_ERROR;
- } break;
- case GET_TOKEN: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- sp<ISurface> sur = interface_cast<ISurface>(data.readStrongBinder());
- ssize_t token = getTokenForSurface(sur);
- reply->writeInt32(token);
- return NO_ERROR;
- } break;
- }
-
- // these must be checked
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- const int self_pid = getpid();
- if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
- // we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.ACCESS_SURFACE_FLINGER")))
- {
- LOGE("Permission Denial: "
- "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- }
-
switch(code) {
case CREATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
diff --git a/libs/gui/SharedBufferStack.cpp b/libs/gui/SharedBufferStack.cpp
deleted file mode 100644
index 7505d53..0000000
--- a/libs/gui/SharedBufferStack.cpp
+++ /dev/null
@@ -1,714 +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.
- */
-
-#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/surfaceflinger/SharedBufferStack.h>
-
-#include <ui/Rect.h>
-#include <ui/Region.h>
-
-#define DEBUG_ATOMICS 0
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-SharedClient::SharedClient()
- : lock(Mutex::SHARED), cv(Condition::SHARED)
-{
-}
-
-SharedClient::~SharedClient() {
-}
-
-
-// these functions are used by the clients
-status_t SharedClient::validate(size_t i) const {
- if (uint32_t(i) >= uint32_t(SharedBufferStack::NUM_LAYERS_MAX))
- return BAD_INDEX;
- return surfaces[i].status;
-}
-
-// ----------------------------------------------------------------------------
-
-
-SharedBufferStack::SharedBufferStack()
-{
-}
-
-void SharedBufferStack::init(int32_t i)
-{
- status = NO_ERROR;
- identity = i;
-}
-
-status_t SharedBufferStack::setCrop(int buffer, const Rect& crop)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
-
- buffers[buffer].crop.l = uint16_t(crop.left);
- buffers[buffer].crop.t = uint16_t(crop.top);
- buffers[buffer].crop.r = uint16_t(crop.right);
- buffers[buffer].crop.b = uint16_t(crop.bottom);
- return NO_ERROR;
-}
-
-status_t SharedBufferStack::setTransform(int buffer, uint8_t transform)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
- buffers[buffer].transform = transform;
- return NO_ERROR;
-}
-
-status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return BAD_INDEX;
-
- FlatRegion& reg(buffers[buffer].dirtyRegion);
- if (dirty.isEmpty()) {
- reg.count = 0;
- return NO_ERROR;
- }
-
- size_t count;
- Rect const* r = dirty.getArray(&count);
- if (count > FlatRegion::NUM_RECT_MAX) {
- const Rect bounds(dirty.getBounds());
- reg.count = 1;
- reg.rects[0].l = uint16_t(bounds.left);
- reg.rects[0].t = uint16_t(bounds.top);
- reg.rects[0].r = uint16_t(bounds.right);
- reg.rects[0].b = uint16_t(bounds.bottom);
- } else {
- reg.count = count;
- for (size_t i=0 ; i<count ; i++) {
- reg.rects[i].l = uint16_t(r[i].left);
- reg.rects[i].t = uint16_t(r[i].top);
- reg.rects[i].r = uint16_t(r[i].right);
- reg.rects[i].b = uint16_t(r[i].bottom);
- }
- }
- return NO_ERROR;
-}
-
-Region SharedBufferStack::getDirtyRegion(int buffer) const
-{
- Region res;
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return res;
-
- const FlatRegion& reg(buffers[buffer].dirtyRegion);
- if (reg.count > FlatRegion::NUM_RECT_MAX)
- return res;
-
- if (reg.count == 1) {
- const Rect r(
- reg.rects[0].l,
- reg.rects[0].t,
- reg.rects[0].r,
- reg.rects[0].b);
- res.set(r);
- } else {
- for (size_t i=0 ; i<reg.count ; i++) {
- const Rect r(
- reg.rects[i].l,
- reg.rects[i].t,
- reg.rects[i].r,
- reg.rects[i].b);
- res.orSelf(r);
- }
- }
- return res;
-}
-
-Rect SharedBufferStack::getCrop(int buffer) const
-{
- Rect res(-1, -1);
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return res;
- res.left = buffers[buffer].crop.l;
- res.top = buffers[buffer].crop.t;
- res.right = buffers[buffer].crop.r;
- res.bottom = buffers[buffer].crop.b;
- return res;
-}
-
-uint32_t SharedBufferStack::getTransform(int buffer) const
-{
- if (uint32_t(buffer) >= NUM_BUFFER_MAX)
- return 0;
- return buffers[buffer].transform;
-}
-
-
-// ----------------------------------------------------------------------------
-
-SharedBufferBase::SharedBufferBase(SharedClient* sharedClient,
- int surface, int32_t identity)
- : mSharedClient(sharedClient),
- mSharedStack(sharedClient->surfaces + surface),
- mIdentity(identity)
-{
-}
-
-SharedBufferBase::~SharedBufferBase()
-{
-}
-
-status_t SharedBufferBase::getStatus() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.status;
-}
-
-int32_t SharedBufferBase::getIdentity() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.identity;
-}
-
-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, identity=%d, status=%d",
- prefix, stack.head, stack.available, stack.queued,
- stack.reallocMask, stack.identity, stack.status);
- result.append(buffer);
- result.append("\n");
- return result;
-}
-
-status_t SharedBufferBase::waitForCondition(const ConditionBase& condition)
-{
- const SharedBufferStack& stack( *mSharedStack );
- SharedClient& client( *mSharedClient );
- const nsecs_t TIMEOUT = s2ns(1);
- const int identity = mIdentity;
-
- Mutex::Autolock _l(client.lock);
- while ((condition()==false) &&
- (stack.identity == identity) &&
- (stack.status == NO_ERROR))
- {
- 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." , condition.name(), stack.identity);
- break;
- } else {
- LOGW("waitForCondition(%s) timed out "
- "(identity=%d, status=%d). "
- "CPU may be pegged. trying again.", condition.name(),
- stack.identity, stack.status);
- }
- } else {
- LOGE("waitForCondition(%s) error (%s) ",
- condition.name(), strerror(-err));
- return err;
- }
- }
- }
- return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
-}
-// ============================================================================
-// conditions and updates
-// ============================================================================
-
-SharedBufferClient::DequeueCondition::DequeueCondition(
- SharedBufferClient* sbc) : ConditionBase(sbc) {
-}
-bool SharedBufferClient::DequeueCondition::operator()() const {
- return stack.available > 0;
-}
-
-SharedBufferClient::LockCondition::LockCondition(
- SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) {
-}
-bool SharedBufferClient::LockCondition::operator()() const {
- // NOTE: if stack.head is messed up, we could crash the client
- // or cause some drawing artifacts. This is okay, as long as it is
- // limited to the client.
- return (buf != stack.index[stack.head]);
-}
-
-SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
- SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
- mNumBuffers(numBuffers) {
-}
-bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
- return stack.available == mNumBuffers;
-}
-
-// ----------------------------------------------------------------------------
-
-SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
- : UpdateBase(sbb) {
-}
-ssize_t SharedBufferClient::QueueUpdate::operator()() {
- android_atomic_inc(&stack.queued);
- return NO_ERROR;
-}
-
-SharedBufferClient::DequeueUpdate::DequeueUpdate(SharedBufferBase* sbb)
- : UpdateBase(sbb) {
-}
-ssize_t SharedBufferClient::DequeueUpdate::operator()() {
- if (android_atomic_dec(&stack.available) == 0) {
- LOGW("dequeue probably called from multiple threads!");
- }
- return NO_ERROR;
-}
-
-SharedBufferClient::CancelUpdate::CancelUpdate(SharedBufferBase* sbb,
- int tail, int buf)
- : UpdateBase(sbb), tail(tail), buf(buf) {
-}
-ssize_t SharedBufferClient::CancelUpdate::operator()() {
- stack.index[tail] = buf;
- android_atomic_inc(&stack.available);
- return NO_ERROR;
-}
-
-SharedBufferServer::RetireUpdate::RetireUpdate(
- SharedBufferBase* sbb, int numBuffers)
- : UpdateBase(sbb), numBuffers(numBuffers) {
-}
-ssize_t SharedBufferServer::RetireUpdate::operator()() {
- int32_t head = stack.head;
- if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- // 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));
-
- // lock the buffer before advancing head, which automatically unlocks
- // the buffer we preventively locked upon entering this function
-
- head = (head + 1) % numBuffers;
- const int8_t headBuf = stack.index[head];
- stack.headBuf = headBuf;
-
- // head is only modified here, so we don't need to use cmpxchg
- 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;
-}
-
-SharedBufferServer::StatusUpdate::StatusUpdate(
- SharedBufferBase* sbb, status_t status)
- : UpdateBase(sbb), status(status) {
-}
-
-ssize_t SharedBufferServer::StatusUpdate::operator()() {
- android_atomic_write(status, &stack.status);
- return NO_ERROR;
-}
-
-// ============================================================================
-
-SharedBufferClient::SharedBufferClient(SharedClient* sharedClient,
- int surface, int num, int32_t identity)
- : SharedBufferBase(sharedClient, surface, identity),
- mNumBuffers(num), tail(0)
-{
- SharedBufferStack& stack( *mSharedStack );
- tail = computeTail();
- queued_head = stack.head;
-}
-
-int32_t SharedBufferClient::computeTail() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers;
-}
-
-ssize_t SharedBufferClient::dequeue()
-{
- SharedBufferStack& stack( *mSharedStack );
-
- RWLock::AutoRLock _rd(mLock);
-
- const nsecs_t dequeueTime = systemTime(SYSTEM_TIME_THREAD);
-
- //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);
-
- DequeueUpdate update(this);
- updateCondition( update );
-
- int dequeued = stack.index[tail];
- tail = ((tail+1 >= mNumBuffers) ? 0 : tail+1);
- LOGD_IF(DEBUG_ATOMICS, "dequeued=%d, tail++=%d, %s",
- dequeued, tail, dump("").string());
-
- mDequeueTime[dequeued] = dequeueTime;
-
- return dequeued;
-}
-
-status_t SharedBufferClient::undoDequeue(int buf)
-{
- return cancel(buf);
-}
-
-status_t SharedBufferClient::cancel(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- // calculate the new position of the tail index (essentially tail--)
- int localTail = (tail + mNumBuffers - 1) % mNumBuffers;
- CancelUpdate update(this, localTail, buf);
- status_t err = updateCondition( update );
- if (err == NO_ERROR) {
- tail = localTail;
- }
- return err;
-}
-
-status_t SharedBufferClient::lock(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- LockCondition condition(this, buf);
- status_t err = waitForCondition(condition);
- return err;
-}
-
-status_t SharedBufferClient::queue(int buf)
-{
- RWLock::AutoRLock _rd(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
-
- queued_head = (queued_head + 1) % mNumBuffers;
- stack.index[queued_head] = buf;
-
- QueueUpdate update(this);
- status_t err = updateCondition( update );
- LOGD_IF(DEBUG_ATOMICS, "queued=%d, %s", buf, dump("").string());
-
- const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
- stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
-
- return err;
-}
-
-bool SharedBufferClient::needNewBuffer(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- const uint32_t mask = 1<<(31-buf);
- return (android_atomic_and(~mask, &stack.reallocMask) & mask) != 0;
-}
-
-status_t SharedBufferClient::setCrop(int buf, const Rect& crop)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setCrop(buf, crop);
-}
-
-status_t SharedBufferClient::setTransform(int buf, uint32_t transform)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setTransform(buf, uint8_t(transform));
-}
-
-status_t SharedBufferClient::setDirtyRegion(int buf, const Region& reg)
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.setDirtyRegion(buf, reg);
-}
-
-status_t SharedBufferClient::setBufferCount(
- int bufferCount, const SetBufferCountCallback& ipc)
-{
- SharedBufferStack& stack( *mSharedStack );
- if (uint32_t(bufferCount) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- if (uint32_t(bufferCount) < SharedBufferStack::NUM_BUFFER_MIN)
- return BAD_VALUE;
-
- RWLock::AutoWLock _wr(mLock);
-
- status_t err = ipc(bufferCount);
- if (err == NO_ERROR) {
- mNumBuffers = bufferCount;
- queued_head = (stack.head + stack.queued) % mNumBuffers;
- tail = computeTail();
- }
- return err;
-}
-
-// ----------------------------------------------------------------------------
-
-SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
- int surface, int num, int32_t identity)
- : SharedBufferBase(sharedClient, surface, identity),
- mNumBuffers(num)
-{
- mSharedStack->init(identity);
- mSharedStack->token = surface;
- mSharedStack->head = num-1;
- mSharedStack->available = num;
- mSharedStack->queued = 0;
- mSharedStack->reallocMask = 0;
- memset(mSharedStack->buffers, 0, sizeof(mSharedStack->buffers));
- for (int i=0 ; i<num ; i++) {
- mBufferList.add(i);
- mSharedStack->index[i] = i;
- }
-}
-
-SharedBufferServer::~SharedBufferServer()
-{
-}
-
-ssize_t SharedBufferServer::retireAndLock()
-{
- RWLock::AutoRLock _l(mLock);
-
- RetireUpdate update(this, mNumBuffers);
- ssize_t buf = updateCondition( update );
- if (buf >= 0) {
- if (uint32_t(buf) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
- SharedBufferStack& stack( *mSharedStack );
- buf = stack.index[buf];
- LOGD_IF(DEBUG_ATOMICS && buf>=0, "retire=%d, %s",
- int(buf), dump("").string());
- }
- return buf;
-}
-
-void SharedBufferServer::setStatus(status_t status)
-{
- if (status < NO_ERROR) {
- StatusUpdate update(this, status);
- updateCondition( update );
- }
-}
-
-status_t SharedBufferServer::reallocateAll()
-{
- RWLock::AutoRLock _l(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- uint32_t mask = mBufferList.getMask();
- android_atomic_or(mask, &stack.reallocMask);
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::reallocateAllExcept(int buffer)
-{
- RWLock::AutoRLock _l(mLock);
-
- SharedBufferStack& stack( *mSharedStack );
- BufferList temp(mBufferList);
- temp.remove(buffer);
- uint32_t mask = temp.getMask();
- android_atomic_or(mask, &stack.reallocMask);
- return NO_ERROR;
-}
-
-int32_t SharedBufferServer::getQueuedCount() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.queued;
-}
-
-Region SharedBufferServer::getDirtyRegion(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getDirtyRegion(buf);
-}
-
-Rect SharedBufferServer::getCrop(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getCrop(buf);
-}
-
-uint32_t SharedBufferServer::getTransform(int buf) const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.getTransform(buf);
-}
-
-/*
- * NOTE: this is not thread-safe on the server-side, meaning
- * 'head' cannot move during this operation. The client-side
- * can safely operate an usual.
- *
- */
-status_t SharedBufferServer::resize(int newNumBuffers)
-{
- if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
- (unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
- return BAD_VALUE;
- }
-
- RWLock::AutoWLock _l(mLock);
-
- if (newNumBuffers < mNumBuffers) {
- return shrink(newNumBuffers);
- } else {
- return grow(newNumBuffers);
- }
-}
-
-status_t SharedBufferServer::grow(int newNumBuffers)
-{
- SharedBufferStack& stack( *mSharedStack );
- const int numBuffers = mNumBuffers;
- const int extra = newNumBuffers - numBuffers;
-
- // read the head, make sure it's valid
- int32_t head = stack.head;
- if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
- return BAD_VALUE;
-
- int base = numBuffers;
- int32_t avail = stack.available;
- int tail = head - avail + 1;
-
- if (tail >= 0) {
- int8_t* const index = const_cast<int8_t*>(stack.index);
- const int nb = numBuffers - head;
- memmove(&index[head + extra], &index[head], nb);
- base = head;
- // move head 'extra' ahead, this doesn't impact stack.index[head];
- stack.head = head + extra;
- }
- stack.available += extra;
-
- // fill the new free space with unused buffers
- BufferList::const_iterator curr(mBufferList.free_begin());
- for (int i=0 ; i<extra ; i++) {
- stack.index[base+i] = *curr;
- mBufferList.add(*curr);
- ++curr;
- }
-
- mNumBuffers = newNumBuffers;
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::shrink(int newNumBuffers)
-{
- SharedBufferStack& stack( *mSharedStack );
-
- // Shrinking is only supported if there are no buffers currently dequeued.
- int32_t avail = stack.available;
- int32_t queued = stack.queued;
- if (avail + queued != mNumBuffers) {
- return INVALID_OPERATION;
- }
-
- // Wait for any queued buffers to be displayed.
- BuffersAvailableCondition condition(this, mNumBuffers);
- status_t err = waitForCondition(condition);
- if (err < 0) {
- return err;
- }
-
- // Reset head to index 0 and make it refer to buffer 0. The same renaming
- // (head -> 0) is done in the BufferManager.
- int32_t head = stack.head;
- int8_t* index = const_cast<int8_t*>(stack.index);
- for (int8_t i = 0; i < newNumBuffers; i++) {
- index[i] = i;
- }
- stack.head = 0;
- stack.headBuf = 0;
-
- // Free the buffers from the end of the list that are no longer needed.
- for (int i = newNumBuffers; i < mNumBuffers; i++) {
- mBufferList.remove(i);
- }
-
- // Tell the client to reallocate all the buffers.
- reallocateAll();
-
- mNumBuffers = newNumBuffers;
- stack.available = newNumBuffers;
-
- return NO_ERROR;
-}
-
-SharedBufferStack::Statistics SharedBufferServer::getStats() const
-{
- SharedBufferStack& stack( *mSharedStack );
- return stack.stats;
-}
-
-// ---------------------------------------------------------------------------
-status_t SharedBufferServer::BufferList::add(int value)
-{
- if (uint32_t(value) >= mCapacity)
- return BAD_VALUE;
- uint32_t mask = 1<<(31-value);
- if (mList & mask)
- return ALREADY_EXISTS;
- mList |= mask;
- return NO_ERROR;
-}
-
-status_t SharedBufferServer::BufferList::remove(int value)
-{
- if (uint32_t(value) >= mCapacity)
- return BAD_VALUE;
- uint32_t mask = 1<<(31-value);
- if (!(mList & mask))
- return NAME_NOT_FOUND;
- mList &= ~mask;
- return NO_ERROR;
-}
-
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 0c5767b..4d1d923 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -21,13 +21,15 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <utils/Errors.h>
-#include <utils/threads.h>
#include <utils/CallStack.h>
+#include <utils/Errors.h>
#include <utils/Log.h>
+#include <utils/threads.h>
-#include <binder/IPCThreadState.h>
#include <binder/IMemory.h>
+#include <binder/IPCThreadState.h>
+
+#include <gui/SurfaceTextureClient.h>
#include <ui/DisplayInfo.h>
#include <ui/GraphicBuffer.h>
@@ -35,12 +37,11 @@
#include <ui/GraphicLog.h>
#include <ui/Rect.h>
-#include <surfaceflinger/Surface.h>
#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/Surface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/LayerState.h>
namespace android {
@@ -273,58 +274,10 @@ sp<Surface> SurfaceControl::getSurface() const
// Surface
// ============================================================================
-class SurfaceClient : public Singleton<SurfaceClient>
-{
- // all these attributes are constants
- sp<ISurfaceComposer> mComposerService;
- sp<ISurfaceComposerClient> mClient;
- status_t mStatus;
- SharedClient* mControl;
- sp<IMemoryHeap> mControlMemory;
-
- SurfaceClient()
- : Singleton<SurfaceClient>(), mStatus(NO_INIT)
- {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- mComposerService = sf;
- mClient = sf->createClientConnection();
- if (mClient != NULL) {
- mControlMemory = mClient->getControlBlock();
- if (mControlMemory != NULL) {
- mControl = static_cast<SharedClient *>(
- mControlMemory->getBase());
- if (mControl) {
- mStatus = NO_ERROR;
- }
- }
- }
- }
- friend class Singleton<SurfaceClient>;
-public:
- status_t initCheck() const {
- return mStatus;
- }
- SharedClient* getSharedClient() const {
- return mControl;
- }
- ssize_t getTokenForSurface(const sp<ISurface>& sur) const {
- // TODO: we could cache a few tokens here to avoid an IPC
- return mClient->getTokenForSurface(sur);
- }
- void signalServer() const {
- mComposerService->signal();
- }
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(SurfaceClient);
-
// ---------------------------------------------------------------------------
Surface::Surface(const sp<SurfaceControl>& surface)
- : mBufferMapper(GraphicBufferMapper::get()),
- mClient(SurfaceClient::getInstance()),
- mSharedBufferClient(NULL),
- mInitCheck(NO_INIT),
+ : mInitCheck(NO_INIT),
mSurface(surface->mSurface),
mIdentity(surface->mIdentity),
mFormat(surface->mFormat), mFlags(surface->mFlags),
@@ -334,10 +287,7 @@ Surface::Surface(const sp<SurfaceControl>& surface)
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
- : mBufferMapper(GraphicBufferMapper::get()),
- mClient(SurfaceClient::getInstance()),
- mSharedBufferClient(NULL),
- mInitCheck(NO_INIT)
+ : mInitCheck(NO_INIT)
{
mSurface = interface_cast<ISurface>(ref);
mIdentity = parcel.readInt32();
@@ -382,7 +332,6 @@ status_t Surface::writeToParcel(
}
-
Mutex Surface::sCachedSurfacesLock;
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces;
@@ -422,32 +371,29 @@ void Surface::init()
ANativeWindow::query = query;
ANativeWindow::perform = perform;
- DisplayInfo dinfo;
- SurfaceComposerClient::getDisplayInfo(0, &dinfo);
- const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
- const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
- // FIXME: set real values here
- const_cast<int&>(ANativeWindow::minSwapInterval) = 1;
- const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
- const_cast<uint32_t&>(ANativeWindow::flags) = 0;
-
- mNextBufferTransform = 0;
- mConnected = 0;
- mSwapRectangle.makeInvalid();
- mNextBufferCrop = Rect(0,0);
- // two buffers by default
- mBuffers.setCapacity(2);
- mBuffers.insertAt(0, 2);
-
- if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
- int32_t token = mClient.getTokenForSurface(mSurface);
- if (token >= 0) {
- mSharedBufferClient = new SharedBufferClient(
- mClient.getSharedClient(), token, 2, mIdentity);
- mInitCheck = mClient.getSharedClient()->validate(token);
- } else {
- LOGW("Not initializing the shared buffer client because token = %d",
- token);
+ if (mSurface != NULL) {
+ sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
+ LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
+ if (surfaceTexture != NULL) {
+ mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
+ mSurfaceTextureClient->setUsage(GraphicBuffer::USAGE_HW_RENDER);
+ }
+
+ DisplayInfo dinfo;
+ SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+ const_cast<float&>(ANativeWindow::xdpi) = dinfo.xdpi;
+ const_cast<float&>(ANativeWindow::ydpi) = dinfo.ydpi;
+
+ const_cast<int&>(ANativeWindow::minSwapInterval) =
+ mSurfaceTextureClient->minSwapInterval;
+
+ const_cast<int&>(ANativeWindow::maxSwapInterval) =
+ mSurfaceTextureClient->maxSwapInterval;
+
+ const_cast<uint32_t&>(ANativeWindow::flags) = 0;
+
+ if (mSurfaceTextureClient != 0) {
+ mInitCheck = NO_ERROR;
}
}
}
@@ -456,9 +402,8 @@ Surface::~Surface()
{
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
- mBuffers.clear();
+ mSurfaceTextureClient.clear();
mSurface.clear();
- delete mSharedBufferClient;
IPCThreadState::self()->flushCommands();
}
@@ -473,32 +418,6 @@ status_t Surface::validate(bool inCancelBuffer) const
LOGE("invalid token (identity=%u)", mIdentity);
return mInitCheck;
}
-
- // verify the identity of this surface
- uint32_t identity = mSharedBufferClient->getIdentity();
- if (mIdentity != identity) {
- LOGE("[Surface] using an invalid surface, "
- "identity=%u should be %d",
- mIdentity, identity);
- CallStack stack;
- stack.update();
- stack.dump("Surface");
- return BAD_INDEX;
- }
-
- // check the surface didn't become invalid
- status_t err = mSharedBufferClient->getStatus();
- if (err != NO_ERROR) {
- if (!inCancelBuffer) {
- LOGE("surface (identity=%u) is invalid, err=%d (%s)",
- mIdentity, err, strerror(-err));
- CallStack stack;
- stack.update();
- stack.dump("Surface");
- }
- return err;
- }
-
return NO_ERROR;
}
@@ -509,7 +428,8 @@ sp<IBinder> Surface::asBinder() const {
// ----------------------------------------------------------------------------
int Surface::setSwapInterval(ANativeWindow* window, int interval) {
- return 0;
+ Surface* self = getSelf(window);
+ return self->setSwapInterval(interval);
}
int Surface::dequeueBuffer(ANativeWindow* window,
@@ -554,383 +474,52 @@ int Surface::perform(ANativeWindow* window,
// ----------------------------------------------------------------------------
-bool Surface::needNewBuffer(int bufIdx,
- uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const
-{
- Mutex::Autolock _l(mSurfaceLock);
-
- // Always call needNewBuffer(), since it clears the needed buffers flags
- bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
- bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
- bool newNeewBuffer = needNewBuffer || !validBuffer;
- if (newNeewBuffer) {
- mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
- }
- return newNeewBuffer;
+int Surface::setSwapInterval(int interval) {
+ return mSurfaceTextureClient->setSwapInterval(interval);
}
-int Surface::dequeueBuffer(ANativeWindowBuffer** buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- GraphicLog& logger(GraphicLog::getInstance());
- logger.log(GraphicLog::SF_APP_DEQUEUE_BEFORE, mIdentity, -1);
-
- ssize_t bufIdx = mSharedBufferClient->dequeue();
-
- logger.log(GraphicLog::SF_APP_DEQUEUE_AFTER, mIdentity, bufIdx);
-
- if (bufIdx < 0) {
- LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
- return bufIdx;
- }
-
- // grow the buffer array if needed
- const size_t size = mBuffers.size();
- const size_t needed = bufIdx+1;
- if (size < needed) {
- mBuffers.insertAt(size, needed-size);
- }
-
- uint32_t w, h, format, usage;
- if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) {
- err = getBufferLocked(bufIdx, w, h, format, usage);
- LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)",
- bufIdx, w, h, format, usage, strerror(-err));
- if (err == NO_ERROR) {
- // reset the width/height with the what we get from the buffer
- const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
- 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
- const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
- if (!err && backBuffer==0) {
- err = NO_MEMORY;
- }
-
+int Surface::dequeueBuffer(ANativeWindowBuffer** buffer) {
+ status_t err = mSurfaceTextureClient->dequeueBuffer(buffer);
if (err == NO_ERROR) {
- mDirtyRegion.set(backBuffer->width, backBuffer->height);
- *buffer = backBuffer.get();
- } else {
- mSharedBufferClient->undoDequeue(bufIdx);
+ mDirtyRegion.set(buffer[0]->width, buffer[0]->height);
}
-
return err;
}
-int Surface::cancelBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate(true);
- switch (err) {
- case NO_ERROR:
- // no error, common case
- break;
- case BAD_INDEX:
- // legitimate errors here
- return err;
- default:
- // other errors happen because the surface is now invalid,
- // for instance because it has been destroyed. In this case,
- // we just fail silently (canceling a buffer is not technically
- // an error at this point)
- return NO_ERROR;
- }
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- err = mSharedBufferClient->cancel(bufIdx);
-
- LOGE_IF(err, "error canceling buffer %d (%s)", bufIdx, strerror(-err));
- return err;
+int Surface::cancelBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->cancelBuffer(buffer);
}
-
-int Surface::lockBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- GraphicLog& logger(GraphicLog::getInstance());
- logger.log(GraphicLog::SF_APP_LOCK_BEFORE, mIdentity, bufIdx);
-
- err = mSharedBufferClient->lock(bufIdx);
-
- logger.log(GraphicLog::SF_APP_LOCK_AFTER, mIdentity, bufIdx);
-
- LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err));
- return err;
+int Surface::lockBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->lockBuffer(buffer);
}
-int Surface::queueBuffer(ANativeWindowBuffer* buffer)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- if (mSwapRectangle.isValid()) {
- mDirtyRegion.set(mSwapRectangle);
- }
-
- int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer));
-
- GraphicLog::getInstance().log(GraphicLog::SF_APP_QUEUE, mIdentity, bufIdx);
-
- mSharedBufferClient->setTransform(bufIdx, mNextBufferTransform);
- mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop);
- mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion);
- err = mSharedBufferClient->queue(bufIdx);
- LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
-
- if (err == NO_ERROR) {
- // TODO: can we avoid this IPC if we know there is one pending?
- mClient.signalServer();
- }
- return err;
+int Surface::queueBuffer(ANativeWindowBuffer* buffer) {
+ return mSurfaceTextureClient->queueBuffer(buffer);
}
-int Surface::query(int what, int* value) const
-{
+int Surface::query(int what, int* value) const {
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);
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+ // TODO: this is not needed anymore
+ *value = 1;
return NO_ERROR;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- *value = MIN_UNDEQUEUED_BUFFERS;
- return NO_ERROR;
- case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- *value = sf->authenticateSurface(mSurface) ? 1 : 0;
- return NO_ERROR;
- }
case NATIVE_WINDOW_CONCRETE_TYPE:
+ // TODO: this is not needed anymore
*value = NATIVE_WINDOW_SURFACE;
return NO_ERROR;
}
- return BAD_VALUE;
-}
-
-int Surface::perform(int operation, va_list args)
-{
- status_t err = validate();
- if (err != NO_ERROR)
- return err;
-
- int res = NO_ERROR;
- switch (operation) {
- case NATIVE_WINDOW_SET_USAGE:
- dispatch_setUsage( args );
- break;
- case NATIVE_WINDOW_CONNECT:
- res = dispatch_connect( args );
- break;
- case NATIVE_WINDOW_DISCONNECT:
- res = dispatch_disconnect( args );
- break;
- case NATIVE_WINDOW_SET_CROP:
- res = dispatch_crop( args );
- break;
- case NATIVE_WINDOW_SET_BUFFER_COUNT:
- res = dispatch_set_buffer_count( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
- res = dispatch_set_buffers_geometry( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
- res = dispatch_set_buffers_transform( args );
- break;
- case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
- res = dispatch_set_buffers_timestamp( args );
- break;
- default:
- res = NAME_NOT_FOUND;
- break;
- }
- return res;
-}
-
-void Surface::dispatch_setUsage(va_list args) {
- int usage = va_arg(args, int);
- setUsage( usage );
-}
-int Surface::dispatch_connect(va_list args) {
- int api = va_arg(args, int);
- return connect( api );
-}
-int Surface::dispatch_disconnect(va_list args) {
- int api = va_arg(args, int);
- return disconnect( api );
-}
-int Surface::dispatch_crop(va_list args) {
- android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
- return crop( reinterpret_cast<Rect const*>(rect) );
-}
-int Surface::dispatch_set_buffer_count(va_list args) {
- size_t bufferCount = va_arg(args, size_t);
- return setBufferCount(bufferCount);
-}
-int Surface::dispatch_set_buffers_geometry(va_list args) {
- int w = va_arg(args, int);
- int h = va_arg(args, int);
- int f = va_arg(args, int);
- return setBuffersGeometry(w, h, f);
-}
-
-int Surface::dispatch_set_buffers_transform(va_list args) {
- int transform = va_arg(args, int);
- return setBuffersTransform(transform);
-}
-
-int Surface::dispatch_set_buffers_timestamp(va_list args) {
- int64_t timestamp = va_arg(args, int64_t);
- return setBuffersTimestamp(timestamp);
-}
-
-void Surface::setUsage(uint32_t reqUsage)
-{
- Mutex::Autolock _l(mSurfaceLock);
- mBufferInfo.set(reqUsage);
-}
-
-int Surface::connect(int api)
-{
- Mutex::Autolock _l(mSurfaceLock);
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- if (mConnected) {
- err = -EINVAL;
- } else {
- mConnected = api;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-int Surface::disconnect(int api)
-{
- Mutex::Autolock _l(mSurfaceLock);
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- if (mConnected == api) {
- mConnected = 0;
- } else {
- err = -EINVAL;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-int Surface::crop(Rect const* rect)
-{
- Mutex::Autolock _l(mSurfaceLock);
- // TODO: validate rect size
-
- if (rect == NULL || rect->isEmpty()) {
- mNextBufferCrop = Rect(0,0);
- } else {
- mNextBufferCrop = *rect;
- }
-
- return NO_ERROR;
+ return mSurfaceTextureClient->query(what, value);
}
-int Surface::setBufferCount(int bufferCount)
-{
- sp<ISurface> s(mSurface);
- if (s == 0) return NO_INIT;
-
- class SetBufferCountIPC : public SharedBufferClient::SetBufferCountCallback {
- sp<ISurface> surface;
- virtual status_t operator()(int bufferCount) const {
- return surface->setBufferCount(bufferCount);
- }
- public:
- SetBufferCountIPC(const sp<ISurface>& surface) : surface(surface) { }
- } ipc(s);
-
- status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
- LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
- bufferCount, strerror(-err));
-
- if (err == NO_ERROR) {
- // Clear out any references to the old buffers.
- mBuffers.clear();
- }
-
- return err;
-}
-
-int Surface::setBuffersGeometry(int w, int h, int format)
-{
- if (w<0 || h<0 || format<0)
- return BAD_VALUE;
-
- if ((w && !h) || (!w && h))
- return BAD_VALUE;
-
- Mutex::Autolock _l(mSurfaceLock);
- if (mConnected == NATIVE_WINDOW_API_EGL) {
- return INVALID_OPERATION;
- }
-
- mBufferInfo.set(w, h, format);
- if (format != 0) {
- // we update the format of the surface as reported by query().
- // this is to allow applications to change the format of a surface's
- // buffer, and have it reflected in EGL; which is needed for
- // EGLConfig validation.
- mFormat = format;
- }
-
- mNextBufferCrop = Rect(0,0);
-
- return NO_ERROR;
-}
-
-int Surface::setBuffersTransform(int transform)
-{
- Mutex::Autolock _l(mSurfaceLock);
- mNextBufferTransform = transform;
- return NO_ERROR;
-}
-
-int Surface::setBuffersTimestamp(int64_t timestamp)
-{
- // Surface doesn't really have anything meaningful to do with timestamps
- // so they'll just be dropped here.
- return NO_ERROR;
+int Surface::perform(int operation, va_list args) {
+ return mSurfaceTextureClient->perform(operation, args);
}
// ----------------------------------------------------------------------------
-int Surface::getConnectedApi() const
-{
- Mutex::Autolock _l(mSurfaceLock);
- return mConnected;
+int Surface::getConnectedApi() const {
+ return mSurfaceTextureClient->getConnectedApi();
}
// ----------------------------------------------------------------------------
@@ -967,16 +556,17 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
}
// we're intending to do software rendering from this point
- setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ mSurfaceTextureClient->setUsage(
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
ANativeWindowBuffer* out;
- status_t err = dequeueBuffer(&out);
+ status_t err = mSurfaceTextureClient->dequeueBuffer(&out);
LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
- err = lockBuffer(backBuffer.get());
- LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)",
- getBufferIndex(backBuffer), strerror(-err));
+ err = mSurfaceTextureClient->lockBuffer(backBuffer.get());
+ LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
+ backBuffer->handle, strerror(-err));
if (err == NO_ERROR) {
const Rect bounds(backBuffer->width, backBuffer->height);
const Region boundsRegion(bounds);
@@ -1043,110 +633,14 @@ status_t Surface::unlockAndPost()
status_t err = mLockedBuffer->unlock();
LOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
- err = queueBuffer(mLockedBuffer.get());
- LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)",
- getBufferIndex(mLockedBuffer), strerror(-err));
+ err = mSurfaceTextureClient->queueBuffer(mLockedBuffer.get());
+ LOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
+ mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
-void Surface::setSwapRectangle(const Rect& r) {
- Mutex::Autolock _l(mSurfaceLock);
- mSwapRectangle = r;
-}
-
-int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
-{
- int idx = buffer->getIndex();
- if (idx < 0) {
- // The buffer doesn't have an index set. See if the handle the same as
- // one of the buffers for which we do know the index. This can happen
- // e.g. if GraphicBuffer is used to wrap an ANativeWindowBuffer that
- // was dequeued from an ANativeWindow.
- for (size_t i = 0; i < mBuffers.size(); i++) {
- if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) {
- idx = mBuffers[i]->getIndex();
- break;
- }
- }
- }
- return idx;
-}
-
-status_t Surface::getBufferLocked(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- sp<ISurface> s(mSurface);
- if (s == 0) return NO_INIT;
-
- status_t err = NO_MEMORY;
-
- // free the current buffer
- sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
- if (currentBuffer != 0) {
- currentBuffer.clear();
- }
-
- sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage);
- LOGE_IF(buffer==0,
- "ISurface::getBuffer(%d, %08x) returned NULL",
- index, usage);
- if (buffer != 0) { // this should always happen by construction
- LOGE_IF(buffer->handle == NULL,
- "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
- "returned a buffer with a null handle",
- mIdentity, index, w, h, format, usage);
- err = mSharedBufferClient->getStatus();
- LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err);
- if (!err && buffer->handle != NULL) {
- currentBuffer = buffer;
- currentBuffer->setIndex(index);
- } else {
- err = err<0 ? err : status_t(NO_MEMORY);
- }
- }
- return err;
-}
-
-// ----------------------------------------------------------------------------
-Surface::BufferInfo::BufferInfo()
- : mWidth(0), mHeight(0), mFormat(0),
- mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0)
-{
-}
-
-void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) {
- if ((mWidth != w) || (mHeight != h) || (mFormat != format)) {
- mWidth = w;
- mHeight = h;
- mFormat = format;
- mDirty |= GEOMETRY;
- }
-}
-
-void Surface::BufferInfo::set(uint32_t usage) {
- mUsage = usage;
-}
-
-void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight,
- uint32_t *pFormat, uint32_t *pUsage) const {
- *pWidth = mWidth;
- *pHeight = mHeight;
- *pFormat = mFormat;
- *pUsage = mUsage;
-}
-
-bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const {
- // make sure we AT LEAST have the usage flags we want
- if (mDirty || buffer==0 ||
- ((buffer->usage & mUsage) != mUsage)) {
- mDirty = 0;
- return false;
- }
- return true;
-}
-
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a1ff2c1..1678711 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -20,19 +20,20 @@
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <utils/SortedVector.h>
#include <utils/Log.h>
#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
-#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
+#include <binder/IServiceManager.h>
#include <ui/DisplayInfo.h>
+#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
-#include <surfaceflinger/ISurface.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <private/surfaceflinger/LayerState.h>
@@ -217,7 +218,7 @@ void SurfaceComposerClient::dispose()
status_t SurfaceComposerClient::getDisplayInfo(
DisplayID dpy, DisplayInfo* info)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
@@ -235,7 +236,7 @@ status_t SurfaceComposerClient::getDisplayInfo(
ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -244,7 +245,7 @@ ssize_t SurfaceComposerClient::getDisplayWidth(DisplayID dpy)
ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
@@ -253,7 +254,7 @@ ssize_t SurfaceComposerClient::getDisplayHeight(DisplayID dpy)
ssize_t SurfaceComposerClient::getDisplayOrientation(DisplayID dpy)
{
- if (uint32_t(dpy)>=SharedBufferStack::NUM_DISPLAY_MAX)
+ if (uint32_t(dpy)>=NUM_DISPLAY_MAX)
return BAD_VALUE;
volatile surface_flinger_cblk_t const * cblk = get_cblk();
volatile display_cblk_t const * dcblk = cblk->displays + dpy;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index c20fcf2..22b0852 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -181,6 +181,12 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
int SurfaceTextureClient::query(int what, int* value) const {
LOGV("SurfaceTextureClient::query");
switch (what) {
+ case NATIVE_WINDOW_FORMAT:
+ if (mReqFormat) {
+ *value = mReqFormat;
+ return NO_ERROR;
+ }
+ break;
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
// TODO: this is not needed anymore
*value = 0;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 9daaad8..c618263 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -2,18 +2,18 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- clz.cpp.arm \
- DisplayHardware/DisplayHardware.cpp \
+ Layer.cpp \
+ LayerBase.cpp \
+ LayerDim.cpp \
+ DisplayHardware/DisplayHardware.cpp \
DisplayHardware/DisplayHardwareBase.cpp \
- DisplayHardware/HWComposer.cpp \
- GLExtensions.cpp \
- Layer.cpp \
- LayerBase.cpp \
- LayerDim.cpp \
- MessageQueue.cpp \
- SurfaceFlinger.cpp \
- TextureManager.cpp \
- Transform.cpp
+ DisplayHardware/HWComposer.cpp \
+ GLExtensions.cpp \
+ MessageQueue.cpp \
+ SurfaceFlinger.cpp \
+ SurfaceTextureLayer.cpp \
+ Transform.cpp \
+
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 8df2b92..0137120 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -18,8 +18,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <cutils/properties.h>
+#include <cutils/compiler.h>
#include <cutils/native_handle.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
#include <utils/Log.h>
@@ -31,12 +32,12 @@
#include <surfaceflinger/Surface.h>
#include "clz.h"
+#include "DisplayHardware/DisplayHardware.h"
+#include "DisplayHardware/HWComposer.h"
#include "GLExtensions.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-#include "DisplayHardware/HWComposer.h"
-
+#include "SurfaceTextureLayer.h"
#define DEBUG_RESIZE 0
@@ -52,102 +53,81 @@ template <typename T> inline T min(T a, T b) {
Layer::Layer(SurfaceFlinger* flinger,
DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client),
+ mTextureName(-1U),
+ mQueuedFrames(0),
+ mCurrentTransform(0),
+ mCurrentOpacity(true),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
- mNeedsBlending(true),
+ mOpaqueLayer(true),
mNeedsDithering(false),
mSecure(false),
mProtectedByApp(false),
- mTextureManager(),
- mBufferManager(mTextureManager),
- mWidth(0), mHeight(0),
- mNeedsScaling(false), mFixedSize(false)
-{
-}
-
-Layer::~Layer()
+ mFixedSize(false)
{
- // FIXME: must be called from the main UI thread
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- mBufferManager.destroy(dpy);
-
- // we can use getUserClientUnsafe here because we know we're
- // single-threaded at that point.
- sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
- if (ourClient != 0) {
- ourClient->detachLayer(this);
- }
+ mCurrentCrop.makeInvalid();
+ glGenTextures(1, &mTextureName);
}
void Layer::destroy() const {
mFlinger->destroyLayer(this);
}
-status_t Layer::setToken(const sp<UserClient>& userClient,
- SharedClient* sharedClient, int32_t token)
+void Layer::onFirstRef()
{
- sp<SharedBufferServer> lcblk = new SharedBufferServer(
- sharedClient, token, mBufferManager.getDefaultBufferCount(),
- getIdentity());
-
-
- sp<UserClient> ourClient(mUserClientRef.getClient());
-
- /*
- * Here it is guaranteed that userClient != ourClient
- * (see UserClient::getTokenForSurface()).
- *
- * We release the token used by this surface in ourClient below.
- * This should be safe to do so now, since this layer won't be attached
- * to this client, it should be okay to reuse that id.
- *
- * If this causes problems, an other solution would be to keep a list
- * of all the {UserClient, token} ever used and release them when the
- * Layer is destroyed.
- *
- */
-
- if (ourClient != 0) {
- ourClient->detachLayer(this);
- }
-
- status_t err = mUserClientRef.setToken(userClient, lcblk, token);
- LOGE_IF(err != NO_ERROR,
- "ClientRef::setToken(%p, %p, %u) failed",
- userClient.get(), lcblk.get(), token);
-
- if (err == NO_ERROR) {
- // we need to free the buffers associated with this surface
- }
-
- return err;
+ LayerBaseClient::onFirstRef();
+ struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
+ FrameQueuedListener(Layer* layer) : mLayer(layer) { }
+ private:
+ wp<Layer> mLayer;
+ virtual void onFrameAvailable() {
+ sp<Layer> that(mLayer.promote());
+ if (that != 0) {
+ that->onFrameQueued();
+ }
+ }
+ };
+ mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
+ mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
+ mSurfaceTexture->setSynchronousMode(true);
+ mSurfaceTexture->setBufferCountServer(2);
}
-int32_t Layer::getToken() const
+Layer::~Layer()
{
- return mUserClientRef.getToken();
+ glDeleteTextures(1, &mTextureName);
}
-sp<UserClient> Layer::getClient() const
-{
- return mUserClientRef.getClient();
+void Layer::onFrameQueued() {
+ if (android_atomic_or(1, &mQueuedFrames) == 0) {
+ mFlinger->signalEvent();
+ }
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (lcblk) {
- // wake up the condition
- lcblk->setStatus(NO_INIT);
- }
}
-sp<LayerBaseClient::Surface> Layer::createSurface() const
+sp<ISurface> Layer::createSurface()
{
- sp<Surface> sur(new SurfaceLayer(mFlinger, const_cast<Layer *>(this)));
+ class BSurface : public BnSurface, public LayerCleaner {
+ wp<const Layer> mOwner;
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const {
+ sp<ISurfaceTexture> res;
+ sp<const Layer> that( mOwner.promote() );
+ if (that != NULL) {
+ res = that->mSurfaceTexture;
+ }
+ return res;
+ }
+ public:
+ BSurface(const sp<SurfaceFlinger>& flinger,
+ const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), mOwner(layer) { }
+ };
+ sp<ISurface> sur(new BSurface(mFlinger, this));
return sur;
}
@@ -175,17 +155,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
const uint32_t hwFlags = hw.getFlags();
mFormat = format;
- mWidth = w;
- mHeight = h;
-
- mReqFormat = format;
- mReqWidth = w;
- mReqHeight = h;
mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
- mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 &&
- (flags & ISurfaceComposer::eOpaque) == 0;
+ mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
+ mCurrentOpacity = getOpacityForFormat(format);
+
+ mSurfaceTexture->setDefaultBufferSize(w, h);
+ mSurfaceTexture->setDefaultBufferFormat(format);
// we use the red index
int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
@@ -216,10 +193,12 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
return;
}
- Transform tr(Transform(mOrientation) * Transform(mBufferTransform));
+ // FIXME: shouldn't we take the state's transform into account here?
+
+ Transform tr(Transform(mOrientation) * Transform(mCurrentTransform));
hwcl->transform = tr.getOrientation();
- if (needsBlending()) {
+ if (!isOpaque()) {
hwcl->blending = mPremultipliedAlpha ?
HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
}
@@ -236,7 +215,7 @@ void Layer::setGeometry(hwc_layer_t* hwcl)
}
void Layer::setPerFrameData(hwc_layer_t* hwcl) {
- sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
+ const sp<GraphicBuffer>& buffer(mActiveBuffer);
if (buffer == NULL) {
// this can happen if the client never drew into this layer yet,
// or if we ran out of memory. In that case, don't let
@@ -247,11 +226,11 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
}
hwcl->handle = buffer->handle;
- if (!mBufferCrop.isEmpty()) {
- hwcl->sourceCrop.left = mBufferCrop.left;
- hwcl->sourceCrop.top = mBufferCrop.top;
- hwcl->sourceCrop.right = mBufferCrop.right;
- hwcl->sourceCrop.bottom = mBufferCrop.bottom;
+ if (isCropped()) {
+ hwcl->sourceCrop.left = mCurrentCrop.left;
+ hwcl->sourceCrop.top = mCurrentCrop.top;
+ hwcl->sourceCrop.right = mCurrentCrop.right;
+ hwcl->sourceCrop.bottom = mCurrentCrop.bottom;
} else {
hwcl->sourceCrop.left = 0;
hwcl->sourceCrop.top = 0;
@@ -260,51 +239,12 @@ void Layer::setPerFrameData(hwc_layer_t* hwcl) {
}
}
-void Layer::reloadTexture(const Region& dirty)
-{
- sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
- if (buffer == NULL) {
- // this situation can happen if we ran out of memory for instance.
- // not much we can do. continue to use whatever texture was bound
- // to this context.
- return;
- }
-
- if (mGLExtensions.haveDirectTexture()) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
- // not sure what we can do here...
- goto slowpath;
- }
- } else {
-slowpath:
- GGLSurface t;
- if (buffer->usage & GRALLOC_USAGE_SW_READ_MASK) {
- status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
- LOGE_IF(res, "error %d (%s) locking buffer %p",
- res, strerror(res), buffer.get());
- if (res == NO_ERROR) {
- mBufferManager.loadTexture(dirty, t);
- buffer->unlock();
- }
- } else {
- // we can't do anything
- }
- }
-}
-
-void Layer::drawForSreenShot() const
-{
- const bool currentFiltering = mNeedsFiltering;
- const_cast<Layer*>(this)->mNeedsFiltering = true;
- LayerBase::drawForSreenShot();
- const_cast<Layer*>(this)->mNeedsFiltering = currentFiltering;
+static inline uint16_t pack565(int r, int g, int b) {
+ return (r<<11)|(g<<5)|b;
}
-
void Layer::onDraw(const Region& clip) const
{
- Texture tex(mBufferManager.getActiveTexture());
- if (tex.name == -1LU) {
+ if (CC_UNLIKELY(mActiveBuffer == 0)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. This happens frequently with
// SurfaceView because the WindowManager can't know when the client
@@ -330,7 +270,25 @@ void Layer::onDraw(const Region& clip) const
}
return;
}
- drawWithOpenGL(clip, tex);
+
+ GLenum target = mSurfaceTexture->getCurrentTextureTarget();
+ glBindTexture(target, mTextureName);
+ if (getFiltering() || needsFiltering() || isFixedSize() || isCropped()) {
+ // TODO: we could be more subtle with isFixedSize()
+ glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ glEnable(target);
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf(mTextureMatrix);
+ glMatrixMode(GL_MODELVIEW);
+
+ drawWithOpenGL(clip);
+
+ glDisable(target);
}
// As documented in libhardware header, formats in the range
@@ -340,186 +298,37 @@ void Layer::onDraw(const Region& clip) const
// hardware.h, instead of using hard-coded values here.
#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-bool Layer::needsBlending(const sp<GraphicBuffer>& buffer) const
+bool Layer::getOpacityForFormat(uint32_t format)
{
- // If buffers where set with eOpaque flag, all buffers are known to
- // be opaque without having to check their actual format
- if (mNeedsBlending && buffer != NULL) {
- PixelFormat format = buffer->getPixelFormat();
-
- if (HARDWARE_IS_DEVICE_FORMAT(format)) {
- return false;
- }
-
- PixelFormatInfo info;
- status_t err = getPixelFormatInfo(format, &info);
- if (!err && info.h_alpha <= info.l_alpha) {
- return false;
- }
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return true;
}
-
- // Return opacity as determined from flags and format options
- // passed to setBuffers()
- return mNeedsBlending;
+ PixelFormatInfo info;
+ status_t err = getPixelFormatInfo(PixelFormat(format), &info);
+ // in case of error (unknown format), we assume no blending
+ return (err || info.h_alpha <= info.l_alpha);
}
-bool Layer::needsBlending() const
-{
- if (mBufferManager.hasActiveBuffer()) {
- return needsBlending(mBufferManager.getActiveBuffer());
- }
- return mNeedsBlending;
-}
-
-bool Layer::needsFiltering() const
+bool Layer::isOpaque() const
{
- if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
- // if our buffer is not the same size than ourselves,
- // we need filtering.
- Mutex::Autolock _l(mLock);
- if (mNeedsScaling)
- return true;
- }
- return LayerBase::needsFiltering();
+ // if we don't have a buffer yet, we're translucent regardless of the
+ // layer's opaque flag.
+ if (mActiveBuffer == 0)
+ return false;
+
+ // if the layer has the opaque flag, then we're always opaque,
+ // otherwise we use the current buffer's format.
+ return mOpaqueLayer || mCurrentOpacity;
}
bool Layer::isProtected() const
{
- sp<GraphicBuffer> activeBuffer(mBufferManager.getActiveBuffer());
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
return (activeBuffer != 0) &&
(activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
}
-status_t Layer::setBufferCount(int bufferCount)
-{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // oops, the client is already gone
- return DEAD_OBJECT;
- }
-
- // NOTE: lcblk->resize() is protected by an internal lock
- status_t err = lcblk->resize(bufferCount);
- if (err == NO_ERROR) {
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
- mBufferManager.resize(bufferCount, mFlinger, dpy);
- }
-
- return err;
-}
-
-sp<GraphicBuffer> Layer::requestBuffer(int index,
- uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
- uint32_t usage)
-{
- sp<GraphicBuffer> buffer;
-
- if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
- return buffer;
-
- if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
- return buffer;
-
- // this ensures our client doesn't go away while we're accessing
- // the shared area.
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // oops, the client is already gone
- return buffer;
- }
-
- /*
- * 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.
- */
-
- status_t err = NO_ERROR;
- uint32_t w, h, f;
- { // scope for the lock
- Mutex::Autolock _l(mLock);
-
- // zero means default
- const bool fixedSize = reqWidth && reqHeight;
- if (!reqFormat) reqFormat = mFormat;
- if (!reqWidth) reqWidth = mWidth;
- if (!reqHeight) reqHeight = mHeight;
-
- w = reqWidth;
- h = reqHeight;
- f = reqFormat;
-
- if ((reqWidth != mReqWidth) || (reqHeight != mReqHeight) ||
- (reqFormat != mReqFormat)) {
- mReqWidth = reqWidth;
- mReqHeight = reqHeight;
- mReqFormat = reqFormat;
- mFixedSize = fixedSize;
- mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
-
- lcblk->reallocateAllExcept(index);
- }
- }
-
- // here we have to reallocate a new buffer because the buffer could be
- // used as the front buffer, or by a client in our process
- // (eg: status bar), and we can't release the handle under its feet.
- const uint32_t effectiveUsage = getEffectiveUsage(usage);
- buffer = new GraphicBuffer(w, h, f, effectiveUsage);
- err = buffer->initCheck();
-
- if (err || buffer->handle == 0) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- 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 {
- LOGD_IF(DEBUG_RESIZE,
- "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
- this, index, w, h, buffer->handle);
- }
-
- if (err == NO_ERROR && buffer->handle != 0) {
- Mutex::Autolock _l(mLock);
- mBufferManager.attachBuffer(index, buffer);
- }
- return buffer;
-}
-
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
- /*
- * buffers used for software rendering, but h/w composition
- * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
- *
- * buffers used for h/w rendering and h/w composition
- * are allocated with HW_RENDER | HW_TEXTURE
- *
- * buffers used with h/w rendering and either NPOT or no egl_image_ext
- * are allocated with SW_READ_RARELY | HW_RENDER
- *
- */
-
- if (mSecure) {
- // secure buffer, don't store it into the GPU
- usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
- GraphicBuffer::USAGE_SW_WRITE_OFTEN;
- } else {
- // it's allowed to modify the usage flags here, but generally
- // the requested flags should be honored.
- // request EGLImage for all buffers
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- }
- if (mProtectedByApp) {
- // need a hardware-protected path to external video sink
- usage |= GraphicBuffer::USAGE_PROTECTED;
- }
- return usage;
-}
-
uint32_t Layer::doTransaction(uint32_t flags)
{
const Layer::State& front(drawingState());
@@ -531,10 +340,12 @@ uint32_t Layer::doTransaction(uint32_t flags)
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
+ "resize (layer=%p), requested (%dx%d), drawing (%d,%d), "
+ "fixedSize=%d",
this,
int(temp.requested_w), int(temp.requested_h),
- int(front.requested_w), int(front.requested_h));
+ int(front.requested_w), int(front.requested_h),
+ isFixedSize());
if (!isFixedSize()) {
// we're being resized and there is a freeze display request,
@@ -557,17 +368,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- setBufferSize(temp.requested_w, temp.requested_h);
-
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (lcblk) {
- // all buffers need reallocation
- lcblk->reallocateAll();
- }
- } else {
- // record the new size
- setBufferSize(temp.requested_w, temp.requested_h);
+ mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h);
}
}
@@ -582,16 +383,19 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-void Layer::setBufferSize(uint32_t w, uint32_t h) {
+bool Layer::isFixedSize() const {
Mutex::Autolock _l(mLock);
- mWidth = w;
- mHeight = h;
- mNeedsScaling = mWidth != mReqWidth || mHeight != mReqHeight;
+ return mFixedSize;
}
-bool Layer::isFixedSize() const {
+void Layer::setFixedSize(bool fixedSize)
+{
Mutex::Autolock _l(mLock);
- return mFixedSize;
+ mFixedSize = fixedSize;
+}
+
+bool Layer::isCropped() const {
+ return !mCurrentCrop.isEmpty();
}
// ----------------------------------------------------------------------------
@@ -600,61 +404,48 @@ bool Layer::isFixedSize() const {
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- if (!lcblk) {
- // client died
- recomputeVisibleRegions = true;
- return;
- }
-
- ssize_t buf = lcblk->retireAndLock();
- if (buf == NOT_ENOUGH_DATA) {
- // NOTE: This is not an error, it simply means there is nothing to
- // retire. The buffer is locked because we will use it
- // for composition later in the loop
- return;
- }
-
- if (buf < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
- mPostedDirtyRegion.clear();
- return;
- }
+ if (android_atomic_and(0, &mQueuedFrames)) {
+ if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
+ // something happened!
+ recomputeVisibleRegions = true;
+ return;
+ }
- // we retired a buffer, which becomes the new front buffer
+ // signal another event if we have more frames waiting
+ if (mSurfaceTexture->getQueuedCount()) {
+ if (android_atomic_or(1, &mQueuedFrames) == 0) {
+ mFlinger->signalEvent();
+ }
+ }
- const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
- const bool activeBlending =
- noActiveBuffer ? true : needsBlending(mBufferManager.getActiveBuffer());
+ mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
+ mSurfaceTexture->getTransformMatrix(mTextureMatrix);
- if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
- mPostedDirtyRegion.clear();
- return;
- }
-
- if (noActiveBuffer) {
- // we didn't have an active buffer, we need to recompute
- // our visible region
- recomputeVisibleRegions = true;
- }
+ const Rect crop(mSurfaceTexture->getCurrentCrop());
+ const uint32_t transform(mSurfaceTexture->getCurrentTransform());
+ if ((crop != mCurrentCrop) || (transform != mCurrentTransform)) {
+ mCurrentCrop = crop;
+ mCurrentTransform = transform;
+ mFlinger->invalidateHwcGeometry();
+ }
- sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
- if (newFrontBuffer != NULL) {
- if (!noActiveBuffer && activeBlending != needsBlending(newFrontBuffer)) {
- // new buffer has different opacity than previous active buffer, need
- // to recompute visible regions accordingly
+ const bool opacity(getOpacityForFormat(mActiveBuffer->format));
+ if (opacity != mCurrentOpacity) {
+ mCurrentOpacity = opacity;
recomputeVisibleRegions = true;
}
- // get the dirty region
- // compute the posted region
- const Region dirty(lcblk->getDirtyRegion(buf));
- mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
+ const GLenum target(mSurfaceTexture->getCurrentTextureTarget());
+ glTexParameterx(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// update the layer size and release freeze-lock
const Layer::State& front(drawingState());
+
+ // FIXME: mPostedDirtyRegion = dirty & bounds
+ mPostedDirtyRegion.set(front.w, front.h);
+
+ sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
if ((newFrontBuffer->getWidth() == front.requested_w &&
newFrontBuffer->getHeight() == front.requested_h) ||
isFixedSize())
@@ -685,35 +476,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// we now have the correct size, unfreeze the screen
mFreezeLock.clear();
}
-
- // get the crop region
- setBufferCrop( lcblk->getCrop(buf) );
-
- // get the transformation
- setBufferTransform( lcblk->getTransform(buf) );
-
- } else {
- // this should not happen unless we ran out of memory while
- // allocating the buffer. we're hoping that things will get back
- // to normal the next time the app tries to draw into this buffer.
- // meanwhile, pretend the screen didn't update.
- mPostedDirtyRegion.clear();
- }
-
- if (lcblk->getQueuedCount()) {
- // signal an event if we have more buffers waiting
- mFlinger->signalEvent();
}
-
- /* a buffer was posted, so we need to call reloadTexture(), which
- * will update our internal data structures (eg: EGLImageKHR or
- * texture names). we need to do this even if mPostedDirtyRegion is
- * empty -- it's orthogonal to the fact that a new buffer was posted,
- * for instance, a degenerate case could be that the user did an empty
- * update but repainted the buffer with appropriate content (after a
- * resize for instance).
- */
- reloadTexture( mPostedDirtyRegion );
}
void Layer::unlockPageFlip(
@@ -746,329 +509,36 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
{
LayerBaseClient::dump(result, buffer, SIZE);
- ClientRef::Access sharedClient(mUserClientRef);
- SharedBufferServer* lcblk(sharedClient.get());
- uint32_t totalTime = 0;
- if (lcblk) {
- SharedBufferStack::Statistics stats = lcblk->getStats();
- totalTime= stats.totalTime;
- result.append( lcblk->dump(" ") );
- }
-
- sp<const GraphicBuffer> buf0(getBuffer(0));
- sp<const GraphicBuffer> buf1(getBuffer(1));
- uint32_t w0=0, h0=0, s0=0;
- uint32_t w1=0, h1=0, s1=0;
+ sp<const GraphicBuffer> buf0(mActiveBuffer);
+ uint32_t w0=0, h0=0, s0=0, f0=0;
if (buf0 != 0) {
w0 = buf0->getWidth();
h0 = buf0->getHeight();
s0 = buf0->getStride();
- }
- if (buf1 != 0) {
- w1 = buf1->getWidth();
- h1 = buf1->getHeight();
- s1 = buf1->getStride();
+ f0 = buf0->format;
}
snprintf(buffer, SIZE,
" "
- "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
- " freezeLock=%p, dq-q-time=%u us\n",
- mFormat, w0, h0, s0, w1, h1, s1,
- getFreezeLock().get(), totalTime);
+ "format=%2d, activeBuffer=[%3ux%3u:%3u,%3u],"
+ " freezeLock=%p, queued-frames=%d\n",
+ mFormat, w0, h0, s0,f0,
+ getFreezeLock().get(), mQueuedFrames);
result.append(buffer);
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::ClientRef::ClientRef()
- : mControlBlock(0), mToken(-1) {
-}
-
-Layer::ClientRef::~ClientRef() {
-}
-
-int32_t Layer::ClientRef::getToken() const {
- Mutex::Autolock _l(mLock);
- return mToken;
-}
-
-sp<UserClient> Layer::ClientRef::getClient() const {
- Mutex::Autolock _l(mLock);
- return mUserClient.promote();
-}
-
-status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
- const sp<SharedBufferServer>& sharedClient, int32_t token) {
- Mutex::Autolock _l(mLock);
-
- { // scope for strong mUserClient reference
- sp<UserClient> userClient(mUserClient.promote());
- if (userClient != 0 && mControlBlock != 0) {
- mControlBlock->setStatus(NO_INIT);
- }
- }
-
- mUserClient = uc;
- mToken = token;
- mControlBlock = sharedClient;
- return NO_ERROR;
-}
-
-sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
- return mUserClient.promote();
-}
-
-// this class gives us access to SharedBufferServer safely
-// it makes sure the UserClient (and its associated shared memory)
-// won't go away while we're accessing it.
-Layer::ClientRef::Access::Access(const ClientRef& ref)
- : mControlBlock(0)
-{
- Mutex::Autolock _l(ref.mLock);
- mUserClientStrongRef = ref.mUserClient.promote();
- if (mUserClientStrongRef != 0)
- mControlBlock = ref.mControlBlock;
-}
-
-Layer::ClientRef::Access::~Access()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::BufferManager::BufferManager(TextureManager& tm)
- : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
- mActiveBufferIndex(-1), mFailover(false)
-{
-}
-
-Layer::BufferManager::~BufferManager()
-{
-}
-
-status_t Layer::BufferManager::resize(size_t size,
- const sp<SurfaceFlinger>& flinger, EGLDisplay dpy)
-{
- Mutex::Autolock _l(mLock);
-
- if (size < mNumBuffers) {
- // If there is an active texture, move it into slot 0 if needed
- if (mActiveBufferIndex > 0) {
- BufferData activeBufferData = mBufferData[mActiveBufferIndex];
- mBufferData[mActiveBufferIndex] = mBufferData[0];
- mBufferData[0] = activeBufferData;
- mActiveBufferIndex = 0;
- }
-
- // Free the buffers that are no longer needed.
- for (size_t i = size; i < mNumBuffers; i++) {
- mBufferData[i].buffer = 0;
-
- // Create a message to destroy the textures on SurfaceFlinger's GL
- // thread.
- class MessageDestroyTexture : public MessageBase {
- Image mTexture;
- EGLDisplay mDpy;
- public:
- MessageDestroyTexture(const Image& texture, EGLDisplay dpy)
- : mTexture(texture), mDpy(dpy) { }
- virtual bool handler() {
- status_t err = Layer::BufferManager::destroyTexture(
- &mTexture, mDpy);
- LOGE_IF(err<0, "error destroying texture: %d (%s)",
- mTexture.name, strerror(-err));
- return true; // XXX: err == 0; ????
- }
- };
-
- MessageDestroyTexture *msg = new MessageDestroyTexture(
- mBufferData[i].texture, dpy);
-
- // Don't allow this texture to be cleaned up by
- // BufferManager::destroy.
- mBufferData[i].texture.name = -1U;
- mBufferData[i].texture.image = EGL_NO_IMAGE_KHR;
-
- // Post the message to the SurfaceFlinger object.
- flinger->postMessageAsync(msg);
- }
- }
-
- mNumBuffers = size;
- return NO_ERROR;
-}
-
-// only for debugging
-sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
- return mBufferData[index].buffer;
-}
-
-status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
- BufferData const * const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- mActiveBuffer = buffers[index].buffer;
- mActiveBufferIndex = index;
- return NO_ERROR;
-}
-
-size_t Layer::BufferManager::getActiveBufferIndex() const {
- return mActiveBufferIndex;
-}
-
-Texture Layer::BufferManager::getActiveTexture() const {
- Texture res;
- if (mFailover || mActiveBufferIndex<0) {
- res = mFailoverTexture;
- } else {
- static_cast<Image&>(res) = mBufferData[mActiveBufferIndex].texture;
- }
- return res;
-}
-
-sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
- return mActiveBuffer;
-}
-
-bool Layer::BufferManager::hasActiveBuffer() const {
- return mActiveBufferIndex >= 0;
-}
-
-sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
-{
- BufferData* const buffers = mBufferData;
- sp<GraphicBuffer> buffer;
- Mutex::Autolock _l(mLock);
- buffer = buffers[index].buffer;
- buffers[index].buffer = 0;
- return buffer;
-}
-
-status_t Layer::BufferManager::attachBuffer(size_t index,
- const sp<GraphicBuffer>& buffer)
-{
- BufferData* const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- buffers[index].buffer = buffer;
- buffers[index].texture.dirty = true;
- return NO_ERROR;
-}
-status_t Layer::BufferManager::destroy(EGLDisplay dpy)
-{
- BufferData* const buffers = mBufferData;
- size_t num;
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- buffers[i].buffer = 0;
- }
+ if (mSurfaceTexture != 0) {
+ mSurfaceTexture->dump(result, " ", buffer, SIZE);
}
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&buffers[i].texture, dpy);
- }
- destroyTexture(&mFailoverTexture, dpy);
- return NO_ERROR;
}
-status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& buffer)
-{
- status_t err = NO_INIT;
- ssize_t index = mActiveBufferIndex;
- if (index >= 0) {
- if (!mFailover) {
- {
- // Without that lock, there is a chance of race condition
- // where while composing a specific index, requestBuf
- // with the same index can be executed and touch the same data
- // that is being used in initEglImage.
- // (e.g. dirty flag in texture)
- Mutex::Autolock _l(mLock);
- Image& texture(mBufferData[index].texture);
- err = mTextureManager.initEglImage(&texture, dpy, buffer);
- }
- // if EGLImage fails, we switch to regular texture mode, and we
- // free all resources associated with using EGLImages.
- if (err == NO_ERROR) {
- mFailover = false;
- destroyTexture(&mFailoverTexture, dpy);
- } else {
- mFailover = true;
- const size_t num = mNumBuffers;
- for (size_t i=0 ; i<num ; i++) {
- destroyTexture(&mBufferData[i].texture, dpy);
- }
- }
- } else {
- // we failed once, don't try again
- err = BAD_VALUE;
- }
- }
- return err;
-}
-
-status_t Layer::BufferManager::loadTexture(
- const Region& dirty, const GGLSurface& t)
-{
- return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
-}
-
-status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
-{
- if (tex->name != -1U) {
- glDeleteTextures(1, &tex->name);
- tex->name = -1U;
- }
- if (tex->image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, tex->image);
- tex->image = EGL_NO_IMAGE_KHR;
- }
- return NO_ERROR;
-}
-
-// ---------------------------------------------------------------------------
-
-Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
- const sp<Layer>& owner)
- : Surface(flinger, owner->getIdentity(), owner)
-{
-}
-
-Layer::SurfaceLayer::~SurfaceLayer()
-{
-}
-
-sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- sp<GraphicBuffer> buffer;
- sp<Layer> owner(getOwner());
- if (owner != 0) {
- /*
- * requestBuffer() cannot be called from the main thread
- * as it could cause a dead-lock, since it may have to wait
- * on conditions updated my the main thread.
- */
- buffer = owner->requestBuffer(index, w, h, format, usage);
- }
- return buffer;
-}
-
-status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const
{
- status_t err = DEAD_OBJECT;
- sp<Layer> owner(getOwner());
- if (owner != 0) {
- /*
- * setBufferCount() cannot be called from the main thread
- * as it could cause a dead-lock, since it may have to wait
- * on conditions updated my the main thread.
- */
- err = owner->setBufferCount(bufferCount);
+ // TODO: should we do something special if mSecure is set?
+ if (mProtectedByApp) {
+ // need a hardware-protected path to external video sink
+ usage |= GraphicBuffer::USAGE_PROTECTED;
}
- return err;
+ return usage;
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 278d64e..72e290c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,9 +20,11 @@
#include <stdint.h>
#include <sys/types.h>
+#include <gui/SurfaceTexture.h>
+
+#include <pixelflinger/pixelflinger.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
-#include <pixelflinger/pixelflinger.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -30,8 +32,8 @@
#include <GLES/glext.h>
#include "LayerBase.h"
+#include "SurfaceTextureLayer.h"
#include "Transform.h"
-#include "TextureManager.h"
namespace android {
@@ -40,7 +42,6 @@ namespace android {
class FreezeLock;
class Client;
class GLExtensions;
-class UserClient;
// ---------------------------------------------------------------------------
@@ -58,164 +59,59 @@ public:
status_t setBuffers(uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
- // associate a UserClient to this Layer
- status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
- int32_t getToken() const;
- sp<UserClient> getClient() const;
-
// Set this Layer's buffers size
- void setBufferSize(uint32_t w, uint32_t h);
bool isFixedSize() const;
// LayerBase interface
virtual void setGeometry(hwc_layer_t* hwcl);
virtual void setPerFrameData(hwc_layer_t* hwcl);
- virtual void drawForSreenShot() const;
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
virtual void lockPageFlip(bool& recomputeVisibleRegions);
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
- virtual bool needsBlending(const sp<GraphicBuffer>& buffer) const;
- virtual bool needsBlending() const;
+ virtual bool isOpaque() const;
virtual bool needsDithering() const { return mNeedsDithering; }
- virtual bool needsFiltering() const;
virtual bool isSecure() const { return mSecure; }
virtual bool isProtected() const;
- virtual sp<Surface> createSurface() const;
virtual void onRemoved();
// only for debugging
- inline sp<GraphicBuffer> getBuffer(int i) const {
- return mBufferManager.getBuffer(i); }
- // only for debugging
- inline const sp<FreezeLock>& getFreezeLock() const {
- return mFreezeLock; }
+ inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; }
protected:
virtual void destroy() const;
+ virtual void onFirstRef();
virtual void dump(String8& result, char* scratch, size_t size) const;
private:
- void reloadTexture(const Region& dirty);
+ friend class SurfaceTextureLayer;
+ void onFrameQueued();
+ virtual sp<ISurface> createSurface();
uint32_t getEffectiveUsage(uint32_t usage) const;
- sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- status_t setBufferCount(int bufferCount);
-
- // -----------------------------------------------------------------------
-
- class SurfaceLayer : public LayerBaseClient::Surface {
- public:
- SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
- ~SurfaceLayer();
- private:
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- virtual status_t setBufferCount(int bufferCount);
- sp<Layer> getOwner() const {
- return static_cast<Layer*>(Surface::getOwner().get());
- }
- };
- friend class SurfaceLayer;
+ void setFixedSize(bool fixedSize);
+ bool isCropped() const;
+ static bool getOpacityForFormat(uint32_t format);
// -----------------------------------------------------------------------
- class ClientRef {
- ClientRef(const ClientRef& rhs);
- ClientRef& operator = (const ClientRef& rhs);
- mutable Mutex mLock;
- // binder thread, page-flip thread
- sp<SharedBufferServer> mControlBlock;
- wp<UserClient> mUserClient;
- int32_t mToken;
- public:
- ClientRef();
- ~ClientRef();
- int32_t getToken() const;
- sp<UserClient> getClient() const;
- status_t setToken(const sp<UserClient>& uc,
- const sp<SharedBufferServer>& sharedClient, int32_t token);
- sp<UserClient> getUserClientUnsafe() const;
- class Access {
- Access(const Access& rhs);
- Access& operator = (const Access& rhs);
- sp<UserClient> mUserClientStrongRef;
- sp<SharedBufferServer> mControlBlock;
- public:
- Access(const ClientRef& ref);
- ~Access();
- inline SharedBufferServer* get() const { return mControlBlock.get(); }
- };
- friend class Access;
- };
-
- // -----------------------------------------------------------------------
-
- class BufferManager {
- static const size_t NUM_BUFFERS = 2;
- struct BufferData {
- sp<GraphicBuffer> buffer;
- Image texture;
- };
- // this lock protect mBufferData[].buffer but since there
- // is very little contention, we have only one like for
- // the whole array, we also use it to protect mNumBuffers.
- mutable Mutex mLock;
- BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX];
- size_t mNumBuffers;
- Texture mFailoverTexture;
- TextureManager& mTextureManager;
- ssize_t mActiveBufferIndex;
- sp<GraphicBuffer> mActiveBuffer;
- bool mFailover;
- static status_t destroyTexture(Image* tex, EGLDisplay dpy);
-
- public:
- static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
- BufferManager(TextureManager& tm);
- ~BufferManager();
-
- // detach/attach buffer from/to given index
- sp<GraphicBuffer> detachBuffer(size_t index);
- status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
- // resize the number of active buffers
- status_t resize(size_t size, const sp<SurfaceFlinger>& flinger,
- EGLDisplay dpy);
-
- // ----------------------------------------------
- // must be called from GL thread
-
- // set/get active buffer index
- status_t setActiveBufferIndex(size_t index);
- size_t getActiveBufferIndex() const;
- // return the active buffer
- sp<GraphicBuffer> getActiveBuffer() const;
- // return wether we have an active buffer
- bool hasActiveBuffer() const;
- // return the active texture (or fail-over)
- Texture getActiveTexture() const;
- // frees resources associated with all buffers
- status_t destroy(EGLDisplay dpy);
- // load bitmap data into the active buffer
- status_t loadTexture(const Region& dirty, const GGLSurface& t);
- // make active buffer an EGLImage if needed
- status_t initEglImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& buffer);
-
- // ----------------------------------------------
- // only for debugging
- sp<GraphicBuffer> getBuffer(size_t index) const;
- };
-
- // -----------------------------------------------------------------------
+ // constants
+ sp<SurfaceTextureLayer> mSurfaceTexture;
+ GLuint mTextureName;
// thread-safe
- ClientRef mUserClientRef;
+ volatile int32_t mQueuedFrames;
+
+ // main thread
+ sp<GraphicBuffer> mActiveBuffer;
+ GLfloat mTextureMatrix[16];
+ Rect mCurrentCrop;
+ uint32_t mCurrentTransform;
+ bool mCurrentOpacity;
// constants
PixelFormat mFormat;
const GLExtensions& mGLExtensions;
- bool mNeedsBlending;
+ bool mOpaqueLayer;
bool mNeedsDithering;
// page-flip thread (currently main thread)
@@ -226,18 +122,8 @@ private:
// page-flip thread and transaction thread (currently main thread)
sp<FreezeLock> mFreezeLock;
- // see threading usage in declaration
- TextureManager mTextureManager;
- BufferManager mBufferManager;
-
// binder thread, transaction thread
mutable Mutex mLock;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mReqWidth;
- uint32_t mReqHeight;
- uint32_t mReqFormat;
- bool mNeedsScaling;
bool mFixedSize;
};
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 022f251..bcd8c83 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -32,8 +32,6 @@
#include "LayerBase.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
-#include "TextureManager.h"
-
namespace android {
@@ -44,7 +42,7 @@ int32_t LayerBase::sSequence = 1;
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: dpy(display), contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
- mFlinger(flinger),
+ mFlinger(flinger), mFiltering(false),
mNeedsFiltering(false),
mOrientation(0),
mLeft(0), mTop(0),
@@ -54,8 +52,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
mFlags = hw.getFlags();
- mBufferCrop.makeInvalid();
- mBufferTransform = 0;
}
LayerBase::~LayerBase()
@@ -310,6 +306,16 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
hwcl->handle = NULL;
}
+void LayerBase::setFiltering(bool filtering)
+{
+ mFiltering = filtering;
+}
+
+bool LayerBase::getFiltering() const
+{
+ return mFiltering;
+}
+
void LayerBase::draw(const Region& clip) const
{
// reset GL state
@@ -318,10 +324,12 @@ void LayerBase::draw(const Region& clip) const
onDraw(clip);
}
-void LayerBase::drawForSreenShot() const
+void LayerBase::drawForSreenShot()
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ setFiltering(true);
onDraw( Region(hw.bounds()) );
+ setFiltering(false);
}
void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
@@ -332,8 +340,12 @@ void LayerBase::clearWithOpenGL(const Region& clip, GLclampf red,
const uint32_t fbHeight = hw.getHeight();
glColor4f(red,green,blue,alpha);
- TextureManager::deactivateTextures();
-
+#if defined(GL_OES_EGL_image_external)
+ if (GLExtensions::getInstance().haveTextureExternal()) {
+ glDisable(GL_TEXTURE_EXTERNAL_OES);
+ }
+#endif
+ glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
@@ -354,24 +366,11 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
clearWithOpenGL(clip,0,0,0,0);
}
-template <typename T>
-static inline
-void swap(T& a, T& b) {
- T t(a);
- a = b;
- b = t;
-}
-
-void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
+void LayerBase::drawWithOpenGL(const Region& clip) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
const State& s(drawingState());
-
- // bind our texture
- TextureManager::activateTexture(texture, needsFiltering());
- uint32_t width = texture.width;
- uint32_t height = texture.height;
GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
if (UNLIKELY(s.alpha < 0xFF)) {
@@ -387,7 +386,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
} else {
glColor4f(1, 1, 1, 1);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- if (needsBlending()) {
+ if (!isOpaque()) {
glEnable(GL_BLEND);
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
} else {
@@ -395,86 +394,20 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
}
}
- /*
- * compute texture coordinates
- * here, we handle NPOT, cropping and buffer transformations
- */
-
- GLfloat cl, ct, cr, cb;
- if (!mBufferCrop.isEmpty()) {
- // source is cropped
- const GLfloat us = (texture.NPOTAdjust ? texture.wScale : 1.0f) / width;
- const GLfloat vs = (texture.NPOTAdjust ? texture.hScale : 1.0f) / height;
- cl = mBufferCrop.left * us;
- ct = mBufferCrop.top * vs;
- cr = mBufferCrop.right * us;
- cb = mBufferCrop.bottom * vs;
- } else {
- cl = 0;
- ct = 0;
- cr = (texture.NPOTAdjust ? texture.wScale : 1.0f);
- cb = (texture.NPOTAdjust ? texture.hScale : 1.0f);
- }
-
- /*
- * For the buffer transformation, we apply the rotation last.
- * Since we're transforming the texture-coordinates, we need
- * to apply the inverse of the buffer transformation:
- * inverse( FLIP_V -> FLIP_H -> ROT_90 )
- * <=> inverse( ROT_90 * FLIP_H * FLIP_V )
- * = inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90)
- * = FLIP_V * FLIP_H * ROT_270
- * <=> ROT_270 -> FLIP_H -> FLIP_V
- *
- * The rotation is performed first, in the texture coordinate space.
- *
- */
-
struct TexCoords {
GLfloat u;
GLfloat v;
};
- enum {
- // name of the corners in the texture map
- LB = 0, // left-bottom
- LT = 1, // left-top
- RT = 2, // right-top
- RB = 3 // right-bottom
- };
-
- // vertices in screen space
- int vLT = LB;
- int vLB = LT;
- int vRB = RT;
- int vRT = RB;
-
- // the texture's source is rotated
- uint32_t transform = mBufferTransform;
- if (transform & HAL_TRANSFORM_ROT_90) {
- vLT = RB;
- vLB = LB;
- vRB = LT;
- vRT = RT;
- }
- if (transform & HAL_TRANSFORM_FLIP_V) {
- swap(vLT, vLB);
- swap(vRT, vRB);
- }
- if (transform & HAL_TRANSFORM_FLIP_H) {
- swap(vLT, vRT);
- swap(vLB, vRB);
- }
-
TexCoords texCoords[4];
- texCoords[vLT].u = cl;
- texCoords[vLT].v = ct;
- texCoords[vLB].u = cl;
- texCoords[vLB].v = cb;
- texCoords[vRB].u = cr;
- texCoords[vRB].v = cb;
- texCoords[vRT].u = cr;
- texCoords[vRT].v = ct;
+ texCoords[0].u = 0;
+ texCoords[0].v = 1;
+ texCoords[1].u = 0;
+ texCoords[1].v = 0;
+ texCoords[2].u = 1;
+ texCoords[2].v = 0;
+ texCoords[3].u = 1;
+ texCoords[3].v = 1;
if (needsDithering()) {
glEnable(GL_DITHER);
@@ -497,20 +430,6 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
-void LayerBase::setBufferCrop(const Rect& crop) {
- if (mBufferCrop != crop) {
- mBufferCrop = crop;
- mFlinger->invalidateHwcGeometry();
- }
-}
-
-void LayerBase::setBufferTransform(uint32_t transform) {
- if (mBufferTransform != transform) {
- mBufferTransform = transform;
- mFlinger->invalidateHwcGeometry();
- }
-}
-
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
{
const Layer::State& s(drawingState());
@@ -518,10 +437,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
"+ %s %p\n"
" "
"z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
- "needsBlending=%1d, needsDithering=%1d, invalidate=%1d, "
+ "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
getTypeId(), this, s.z, tx(), ty(), s.w, s.h,
- needsBlending(), needsDithering(), contentDirty,
+ isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
s.transform[1][0], s.transform[1][1]);
@@ -555,9 +474,22 @@ LayerBaseClient::~LayerBaseClient()
}
}
-sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
+sp<ISurface> LayerBaseClient::createSurface()
+{
+ class BSurface : public BnSurface, public LayerCleaner {
+ virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; }
+ public:
+ BSurface(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer)
+ : LayerCleaner(flinger, layer) { }
+ };
+ sp<ISurface> sur(new BSurface(mFlinger, this));
+ return sur;
+}
+
+sp<ISurface> LayerBaseClient::getSurface()
{
- sp<Surface> s;
+ sp<ISurface> s;
Mutex::Autolock _l(mLock);
LOG_ALWAYS_FATAL_IF(mHasSurface,
@@ -573,12 +505,6 @@ wp<IBinder> LayerBaseClient::getSurfaceBinder() const {
return mClientSurfaceBinder;
}
-sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
-{
- return new Surface(mFlinger, mIdentity,
- const_cast<LayerBaseClient *>(this));
-}
-
void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
{
LayerBase::dump(result, buffer, SIZE);
@@ -601,44 +527,14 @@ void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) con
// ---------------------------------------------------------------------------
-LayerBaseClient::Surface::Surface(
- const sp<SurfaceFlinger>& flinger,
- int identity,
- const sp<LayerBaseClient>& owner)
- : mFlinger(flinger), mIdentity(identity), mOwner(owner)
-{
+LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer)
+ : mFlinger(flinger), mLayer(layer) {
}
-LayerBaseClient::Surface::~Surface()
-{
- /*
- * This is a good place to clean-up all client resources
- */
-
+LayerBaseClient::LayerCleaner::~LayerCleaner() {
// destroy client resources
- mFlinger->destroySurface(mOwner);
-}
-
-sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
- sp<LayerBaseClient> owner(mOwner.promote());
- return owner;
-}
-
-status_t LayerBaseClient::Surface::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- return BnSurface::onTransact(code, data, reply, flags);
-}
-
-sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
-{
- return NULL;
-}
-
-status_t LayerBaseClient::Surface::setBufferCount(int bufferCount)
-{
- return INVALID_OPERATION;
+ mFlinger->destroySurface(mLayer);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 6c49a19..faf71dd 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -29,7 +29,6 @@
#include <ui/Region.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
-#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/LayerState.h>
#include <pixelflinger/pixelflinger.h>
@@ -43,13 +42,12 @@ namespace android {
// ---------------------------------------------------------------------------
-class DisplayHardware;
class Client;
+class DisplayHardware;
class GraphicBuffer;
class GraphicPlane;
class LayerBaseClient;
class SurfaceFlinger;
-class Texture;
// ---------------------------------------------------------------------------
@@ -121,7 +119,7 @@ public:
* to perform the actual drawing.
*/
virtual void draw(const Region& clip) const;
- virtual void drawForSreenShot() const;
+ virtual void drawForSreenShot();
/**
* onDraw - draws the surface.
@@ -174,9 +172,9 @@ public:
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
/**
- * needsBlending - true if this surface needs blending
+ * isOpaque - true if this surface is opaque
*/
- virtual bool needsBlending() const { return false; }
+ virtual bool isOpaque() const { return true; }
/**
* needsDithering - true if this surface needs dithering
@@ -184,11 +182,9 @@ public:
virtual bool needsDithering() const { return false; }
/**
- * needsLinearFiltering - true if this surface needs filtering
+ * needsLinearFiltering - true if this surface's state requires filtering
*/
- virtual bool needsFiltering() const {
- return (!(mFlags & DisplayHardware::SLOW_CONFIG)) && mNeedsFiltering;
- }
+ virtual bool needsFiltering() const { return mNeedsFiltering; }
/**
* isSecure - true if this surface is secure, that is if it prevents
@@ -231,21 +227,25 @@ protected:
void clearWithOpenGL(const Region& clip, GLclampf r, GLclampf g,
GLclampf b, GLclampf alpha) const;
void clearWithOpenGL(const Region& clip) const;
- void drawWithOpenGL(const Region& clip, const Texture& texture) const;
-
- // these must be called from the post/drawing thread
- void setBufferCrop(const Rect& crop);
- void setBufferTransform(uint32_t transform);
+ void drawWithOpenGL(const Region& clip) const;
+
+ void setFiltering(bool filtering);
+ bool getFiltering() const;
sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
- // post/drawing thread
- Rect mBufferCrop;
- uint32_t mBufferTransform;
+private:
+ // accessed only in the main thread
+ // Whether filtering is forced on or not
+ bool mFiltering;
// cached during validateVisibility()
+ // Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering;
+
+protected:
+ // cached during validateVisibility()
int32_t mOrientation;
GLfloat mVertices[4][2];
Rect mTransformedBounds;
@@ -281,52 +281,38 @@ private:
class LayerBaseClient : public LayerBase
{
public:
- class Surface;
-
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
- virtual ~LayerBaseClient();
- sp<Surface> getSurface();
+ virtual ~LayerBaseClient();
+
+ sp<ISurface> getSurface();
wp<IBinder> getSurfaceBinder() const;
- virtual sp<Surface> createSurface() const;
+
virtual sp<LayerBaseClient> getLayerBaseClient() const {
return const_cast<LayerBaseClient*>(this); }
+
virtual const char* getTypeId() const { return "LayerBaseClient"; }
uint32_t getIdentity() const { return mIdentity; }
- class Surface : public BnSurface {
- public:
- int32_t getIdentity() const { return mIdentity; }
-
- protected:
- Surface(const sp<SurfaceFlinger>& flinger, int identity,
- const sp<LayerBaseClient>& owner);
- virtual ~Surface();
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags);
- sp<LayerBaseClient> getOwner() const;
-
- private:
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
- uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
- virtual status_t setBufferCount(int bufferCount);
-
- protected:
- friend class LayerBaseClient;
- sp<SurfaceFlinger> mFlinger;
- int32_t mIdentity;
- wp<LayerBaseClient> mOwner;
- };
-
- friend class Surface;
-
protected:
virtual void dump(String8& result, char* scratch, size_t size) const;
virtual void shortDump(String8& result, char* scratch, size_t size) const;
+ class LayerCleaner {
+ sp<SurfaceFlinger> mFlinger;
+ wp<LayerBaseClient> mLayer;
+ protected:
+ ~LayerCleaner();
+ public:
+ LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<LayerBaseClient>& layer);
+ };
+
private:
+ virtual sp<ISurface> createSurface();
+
mutable Mutex mLock;
mutable bool mHasSurface;
wp<IBinder> mClientSurfaceBinder;
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index f79166d..654817d 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -65,8 +65,6 @@ void LayerDim::onDraw(const Region& clip) const
glDisable(GL_TEXTURE_EXTERNAL_OES);
}
#endif
- glDisable(GL_TEXTURE_2D);
-
glVertexPointer(2, GL_FLOAT, 0, mVertices);
while (it != end) {
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index 75f9a89..8770e6d 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -37,7 +37,7 @@ public:
virtual ~LayerDim();
virtual void onDraw(const Region& clip) const;
- virtual bool needsBlending() const { return true; }
+ virtual bool isOpaque() const { return false; }
virtual bool isSecure() const { return false; }
virtual bool isProtectedByApp() const { return false; }
virtual bool isProtectedByDRM() const { return false; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b7a51a4..97edfee 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -53,6 +53,8 @@
#include "DisplayHardware/DisplayHardware.h"
#include "DisplayHardware/HWComposer.h"
+#include <private/surfaceflinger/SharedBufferStack.h>
+
/* ideally AID_GRAPHICS would be in a semi-public header
* or there would be a way to map a user/group name to its id
*/
@@ -133,17 +135,6 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
return bclient;
}
-sp<ISurfaceComposerClient> SurfaceFlinger::createClientConnection()
-{
- sp<ISurfaceComposerClient> bclient;
- sp<UserClient> client(new UserClient(this));
- status_t err = client->initCheck();
- if (err == NO_ERROR) {
- bclient = client;
- }
- return bclient;
-}
-
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{
sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
@@ -322,11 +313,6 @@ void SurfaceFlinger::signalEvent() {
mEventQueue.invalidate();
}
-void SurfaceFlinger::signal() const {
- // this is the IPC call
- const_cast<SurfaceFlinger*>(this)->signalEvent();
-}
-
bool SurfaceFlinger::authenticateSurface(const sp<ISurface>& surface) const {
Mutex::Autolock _l(mStateLock);
sp<IBinder> surfBinder(surface->asBinder());
@@ -658,7 +644,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
- const bool translucent = layer->needsBlending();
+ const bool translucent = !layer->isOpaque();
const Rect bounds(layer->visibleBounds());
visibleRegion.set(bounds);
visibleRegion.andSelf(screenRegion);
@@ -921,7 +907,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
for (size_t i=0 ; i<count ; i++) {
if (cur[i].hints & HWC_HINT_CLEAR_FB) {
const sp<LayerBase>& layer(layers[i]);
- if (!(layer->needsBlending())) {
+ if (layer->isOpaque()) {
transparent.orSelf(layer->visibleRegionScreen);
}
}
@@ -979,8 +965,6 @@ void SurfaceFlinger::debugFlashRegions()
composeSurfaces(repaint);
}
- TextureManager::deactivateTextures();
-
glDisable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
@@ -1070,6 +1054,7 @@ void SurfaceFlinger::drawWormhole() const
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
@@ -1269,7 +1254,7 @@ sp<ISurface> SurfaceFlinger::createSurface(
uint32_t flags)
{
sp<LayerBaseClient> layer;
- sp<LayerBaseClient::Surface> surfaceHandle;
+ sp<ISurface> surfaceHandle;
if (int32_t(w|h) < 0) {
LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
@@ -1300,13 +1285,13 @@ sp<ISurface> SurfaceFlinger::createSurface(
surfaceHandle = layer->getSurface();
if (surfaceHandle != 0) {
params->token = token;
- params->identity = surfaceHandle->getIdentity();
+ params->identity = layer->getIdentity();
params->width = w;
params->height = h;
params->format = format;
if (normalLayer != 0) {
Mutex::Autolock _l(mStateLock);
- mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
+ mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
}
}
@@ -1782,7 +1767,6 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
GLfloat vtx[8];
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
- glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tname);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -1900,6 +1884,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
+ glDisable(GL_TEXTURE_2D);
return NO_ERROR;
}
@@ -1930,7 +1915,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
GLfloat vtx[8];
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
- glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tname);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -2044,6 +2028,7 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
+ glDisable(GL_TEXTURE_2D);
return NO_ERROR;
}
@@ -2408,133 +2393,78 @@ sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
return lbc;
}
-sp<IMemoryHeap> Client::getControlBlock() const {
- return 0;
-}
-ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
- return -1;
+
+status_t Client::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ // these must be checked
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ const int self_pid = getpid();
+ if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
+ // we're called from a different process, do the real check
+ if (!checkCallingPermission(
+ String16("android.permission.ACCESS_SURFACE_FLINGER")))
+ {
+ LOGE("Permission Denial: "
+ "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ }
+ return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
}
+
+
sp<ISurface> Client::createSurface(
ISurfaceComposerClient::surface_data_t* params,
const String8& name,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
- return mFlinger->createSurface(params, name, this,
- display, w, h, format, flags);
-}
-status_t Client::destroySurface(SurfaceID sid) {
- return mFlinger->removeSurface(this, sid);
-}
-status_t Client::setState(int32_t count, const layer_state_t* states) {
- return mFlinger->setClientState(this, count, states);
-}
-
-// ---------------------------------------------------------------------------
-
-UserClient::UserClient(const sp<SurfaceFlinger>& flinger)
- : ctrlblk(0), mBitmap(0), mFlinger(flinger)
-{
- const int pgsize = getpagesize();
- const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
-
- mCblkHeap = new MemoryHeapBase(cblksize, 0,
- "SurfaceFlinger Client control-block");
-
- ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase());
- if (ctrlblk) { // construct the shared structure in-place.
- new(ctrlblk) SharedClient;
- }
-}
-
-UserClient::~UserClient()
-{
- if (ctrlblk) {
- ctrlblk->~SharedClient(); // destroy our shared-structure.
- }
-
/*
- * When a UserClient dies, it's unclear what to do exactly.
- * We could go ahead and destroy all surfaces linked to that client
- * however, it wouldn't be fair to the main Client
- * (usually the the window-manager), which might want to re-target
- * the layer to another UserClient.
- * I think the best is to do nothing, or not much; in most cases the
- * WM itself will go ahead and clean things up when it detects a client of
- * his has died.
- * The remaining question is what to display? currently we keep
- * just keep the current buffer.
+ * createSurface must be called from the GL thread so that it can
+ * have access to the GL context.
*/
-}
-status_t UserClient::initCheck() const {
- return ctrlblk == 0 ? NO_INIT : NO_ERROR;
-}
-
-void UserClient::detachLayer(const Layer* layer)
-{
- int32_t name = layer->getToken();
- if (name >= 0) {
- int32_t mask = 1LU<<name;
- if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
- LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
+ class MessageCreateSurface : public MessageBase {
+ sp<ISurface> result;
+ SurfaceFlinger* flinger;
+ ISurfaceComposerClient::surface_data_t* params;
+ Client* client;
+ const String8& name;
+ DisplayID display;
+ uint32_t w, h;
+ PixelFormat format;
+ uint32_t flags;
+ public:
+ MessageCreateSurface(SurfaceFlinger* flinger,
+ ISurfaceComposerClient::surface_data_t* params,
+ const String8& name, Client* client,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags)
+ : flinger(flinger), params(params), client(client), name(name),
+ display(display), w(w), h(h), format(format), flags(flags)
+ {
}
- }
-}
-
-sp<IMemoryHeap> UserClient::getControlBlock() const {
- return mCblkHeap;
-}
-
-ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
-{
- int32_t name = NAME_NOT_FOUND;
- sp<Layer> layer(mFlinger->getLayer(sur));
- if (layer == 0) {
- return name;
- }
-
- // if this layer already has a token, just return it
- name = layer->getToken();
- if ((name >= 0) && (layer->getClient() == this)) {
- return name;
- }
-
- name = 0;
- do {
- int32_t mask = 1LU<<name;
- if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
- // we found and locked that name
- status_t err = layer->setToken(
- const_cast<UserClient*>(this), ctrlblk, name);
- if (err != NO_ERROR) {
- // free the name
- android_atomic_and(~mask, &mBitmap);
- name = err;
- }
- break;
+ sp<ISurface> getResult() const { return result; }
+ virtual bool handler() {
+ result = flinger->createSurface(params, name, client,
+ display, w, h, format, flags);
+ return true;
}
- if (++name >= int32_t(SharedBufferStack::NUM_LAYERS_MAX))
- name = NO_MEMORY;
- } while(name >= 0);
-
- //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",
- // sur->asBinder().get(), name, this, mBitmap);
- return name;
-}
+ };
-sp<ISurface> UserClient::createSurface(
- ISurfaceComposerClient::surface_data_t* params,
- const String8& name,
- DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags) {
- return 0;
+ sp<MessageBase> msg = new MessageCreateSurface(mFlinger.get(),
+ params, name, this, display, w, h, format, flags);
+ mFlinger->postMessageSync(msg);
+ return static_cast<MessageCreateSurface*>( msg.get() )->getResult();
}
-status_t UserClient::destroySurface(SurfaceID sid) {
- return INVALID_OPERATION;
+status_t Client::destroySurface(SurfaceID sid) {
+ return mFlinger->removeSurface(this, sid);
}
-status_t UserClient::setState(int32_t count, const layer_state_t* states) {
- return INVALID_OPERATION;
+status_t Client::setState(int32_t count, const layer_state_t* states) {
+ return mFlinger->setClientState(this, count, states);
}
// ---------------------------------------------------------------------------
@@ -2547,11 +2477,11 @@ sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h
PixelFormat format, uint32_t usage) {
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
status_t err = graphicBuffer->initCheck();
- if (err != 0) {
- LOGE("createGraphicBuffer: init check failed: %d", err);
- return 0;
- } else if (graphicBuffer->handle == 0) {
- LOGE("createGraphicBuffer: unable to create GraphicBuffer");
+ if (err != 0 || graphicBuffer->handle == 0) {
+ GraphicBuffer::dumpAllocationsToSystemLog();
+ LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) "
+ "failed (%s), handle=%p",
+ w, h, strerror(-err), graphicBuffer->handle);
return 0;
}
return graphicBuffer;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 992861a..af1ef04 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,7 @@ class DisplayHardware;
class FreezeLock;
class Layer;
class LayerDim;
+struct surface_flinger_cblk_t;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -72,14 +73,14 @@ public:
private:
// ISurfaceComposerClient interface
- virtual sp<IMemoryHeap> getControlBlock() const;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
virtual sp<ISurface> createSurface(
surface_data_t* params, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
// constant
sp<SurfaceFlinger> mFlinger;
@@ -92,40 +93,6 @@ private:
mutable Mutex mLock;
};
-class UserClient : public BnSurfaceComposerClient
-{
-public:
- // pointer to this client's control block
- SharedClient* ctrlblk;
-
-public:
- UserClient(const sp<SurfaceFlinger>& flinger);
- ~UserClient();
-
- status_t initCheck() const;
-
- // protected by SurfaceFlinger::mStateLock
- void detachLayer(const Layer* layer);
-
-private:
-
- // ISurfaceComposerClient interface
- virtual sp<IMemoryHeap> getControlBlock() const;
- virtual ssize_t getTokenForSurface(const sp<ISurface>& sur) const;
- virtual sp<ISurface> createSurface(
- surface_data_t* params, const String8& name,
- DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
- uint32_t flags);
- virtual status_t destroySurface(SurfaceID surfaceId);
- virtual status_t setState(int32_t count, const layer_state_t* states);
-
- // atomic-ops
- mutable volatile int32_t mBitmap;
-
- sp<IMemoryHeap> mCblkHeap;
- sp<SurfaceFlinger> mFlinger;
-};
-
class GraphicBufferAlloc : public BnGraphicBufferAlloc
{
public:
@@ -199,7 +166,6 @@ public:
// ISurfaceComposer interface
virtual sp<ISurfaceComposerClient> createConnection();
- virtual sp<ISurfaceComposerClient> createClientConnection();
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
@@ -208,7 +174,6 @@ public:
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
- virtual void signal() const;
virtual bool authenticateSurface(const sp<ISurface>& surface) const;
virtual status_t captureScreen(DisplayID dpy,
@@ -235,7 +200,6 @@ private:
friend class Client;
friend class LayerBase;
friend class LayerBaseClient;
- friend class LayerBaseClient::Surface;
friend class Layer;
friend class LayerDim;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
new file mode 100644
index 0000000..60fa965
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include "Layer.h"
+#include "SurfaceTextureLayer.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+
+SurfaceTextureLayer::SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer)
+ : SurfaceTexture(tex), mLayer(layer) {
+}
+
+SurfaceTextureLayer::~SurfaceTextureLayer() {
+}
+
+
+status_t SurfaceTextureLayer::setDefaultBufferSize(uint32_t w, uint32_t h)
+{
+ //LOGD("%s, w=%u, h=%u", __PRETTY_FUNCTION__, w, h);
+ return SurfaceTexture::setDefaultBufferSize(w, h);
+}
+
+status_t SurfaceTextureLayer::setDefaultBufferFormat(uint32_t format)
+{
+ mDefaultFormat = format;
+ return NO_ERROR;
+}
+
+status_t SurfaceTextureLayer::setBufferCount(int bufferCount) {
+ status_t res = SurfaceTexture::setBufferCount(bufferCount);
+ return res;
+}
+
+status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+
+ status_t res(NO_INIT);
+ sp<Layer> layer(mLayer.promote());
+ if (layer != NULL) {
+ if (format == 0)
+ format = mDefaultFormat;
+ uint32_t effectiveUsage = layer->getEffectiveUsage(usage);
+ //LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
+ // __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
+ res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
+ if (res == NO_ERROR) {
+ layer->setFixedSize(w && h);
+ }
+ }
+ return res;
+}
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
new file mode 100644
index 0000000..7faff54
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 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_SURFACE_TEXTURE_LAYER_H
+#define ANDROID_SURFACE_TEXTURE_LAYER_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <gui/SurfaceTexture.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Layer;
+
+class SurfaceTextureLayer : public SurfaceTexture
+{
+ wp<Layer> mLayer;
+ uint32_t mDefaultFormat;
+
+public:
+ SurfaceTextureLayer(GLuint tex, const sp<Layer>& layer);
+ ~SurfaceTextureLayer();
+
+ status_t setDefaultBufferSize(uint32_t w, uint32_t h);
+ status_t setDefaultBufferFormat(uint32_t format);
+
+public:
+ virtual status_t setBufferCount(int bufferCount);
+
+protected:
+ virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SURFACE_TEXTURE_LAYER_H
diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index 0ddf986..ca44555 100644
--- a/services/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
@@ -20,18 +20,10 @@
namespace android {
-int clz_impl(int32_t x);
-
-int inline clz(int32_t x)
-{
-#if defined(__arm__) && !defined(__thumb__)
+int inline clz(int32_t x) {
return __builtin_clz(x);
-#else
- return clz_impl(x);
-#endif
}
-
}; // namespace android
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */