split surface management from surface's buffers management
Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index dcce25e..c11c855 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -122,7 +122,8 @@
volatile int8_t index[NUM_BUFFER_MAX];
int32_t identity; // surface's identity (const)
- int32_t reserved32[2];
+ int32_t token; // surface's token (for debugging)
+ int32_t reserved32[1];
Statistics stats;
int32_t reserved;
BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 3271cfd..dd44aa5 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -85,9 +85,12 @@
/* create connection with surface flinger, requires
* ACCESS_SURFACE_FLINGER permission
*/
-
virtual sp<ISurfaceComposerClient> createConnection() = 0;
+ /* create a client connection with surface flinger
+ */
+ virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
+
/* retrieve the control block */
virtual sp<IMemoryHeap> getCblk() const = 0;
@@ -123,6 +126,7 @@
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
+ CREATE_CLIENT_CONNECTION,
GET_CBLK,
OPEN_GLOBAL_TRANSACTION,
CLOSE_GLOBAL_TRANSACTION,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index b2a4766..a1e9e04 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -58,6 +58,7 @@
};
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 2957970..67dc693 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -229,7 +229,6 @@
*/
void init();
status_t validate() const;
- status_t initCheck() const;
sp<ISurface> getISurface() const;
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
@@ -264,15 +263,15 @@
};
// constants
- sp<SurfaceClient> mClient;
+ GraphicBufferMapper& mBufferMapper;
+ SurfaceClient& mClient;
+ SharedBufferClient* mSharedBufferClient;
+ status_t mInitCheck;
sp<ISurface> mSurface;
SurfaceID mToken;
uint32_t mIdentity;
PixelFormat mFormat;
uint32_t mFlags;
- GraphicBufferMapper& mBufferMapper;
- SharedBufferClient* mSharedBufferClient;
- status_t mInitCheck;
// protected by mSurfaceLock
Rect mSwapRectangle;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 8e28a81..8773d71 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -22,8 +22,9 @@
#include <binder/IBinder.h>
-#include <utils/SortedVector.h>
#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
#include <utils/threads.h>
#include <ui/PixelFormat.h>
@@ -39,6 +40,22 @@
class SharedClient;
class ISurfaceComposer;
class DisplayInfo;
+class surface_flinger_cblk_t;
+
+// ---------------------------------------------------------------------------
+
+class ComposerService : public Singleton<ComposerService>
+{
+ // these are constants
+ sp<ISurfaceComposer> mComposerService;
+ sp<IMemoryHeap> mServerCblkMemory;
+ surface_flinger_cblk_t volatile* mServerCblk;
+ ComposerService();
+ friend class Singleton<ComposerService>;
+public:
+ static sp<ISurfaceComposer> getComposerService();
+ static surface_flinger_cblk_t const volatile * getControlBlock();
+};
// ---------------------------------------------------------------------------
@@ -153,25 +170,6 @@
};
// ---------------------------------------------------------------------------
-
-class SurfaceClient : public RefBase
-{
- // all these attributes are constants
- status_t mStatus;
- SharedClient* mControl;
- sp<IMemoryHeap> mControlMemory;
- sp<IBinder> mConnection;
- sp<ISurfaceComposer> mComposerService;
- void init(const sp<IBinder>& conn);
-public:
- explicit SurfaceClient(const sp<IBinder>& conn);
- explicit SurfaceClient(const sp<SurfaceComposerClient>& client);
- status_t initCheck() const;
- SharedClient* getSharedClient() const;
- void signalServer() const;
-};
-
-// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index e72b6b3..a3e85a9 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -93,10 +93,8 @@
void setIndex(int index);
int getIndex() const;
- void setVerticalStride(uint32_t vstride);
- uint32_t getVerticalStride() const;
-protected:
+private:
virtual ~GraphicBuffer();
enum {
@@ -105,8 +103,12 @@
ownData = 2,
};
- inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
- inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
+ inline const GraphicBufferMapper& getBufferMapper() const {
+ return mBufferMapper;
+ }
+ inline GraphicBufferMapper& getBufferMapper() {
+ return mBufferMapper;
+ }
uint8_t mOwner;
private:
@@ -134,7 +136,6 @@
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;
- uint32_t mVStride;
int mIndex;
};
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 85149f5f5..a94fdd4 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -50,10 +50,9 @@
Layer::Layer(SurfaceFlinger* flinger,
DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client),
- lcblk(NULL),
- mSecure(false),
mNeedsBlending(true),
mNeedsDithering(false),
+ mSecure(false),
mTextureManager(mFlags),
mBufferManager(mTextureManager),
mWidth(0), mHeight(0), mFixedSize(false)
@@ -66,32 +65,43 @@
EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
mBufferManager.destroy(dpy);
- // the actual buffers will be destroyed here
- delete lcblk;
+ // 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);
+ }
}
-// TODO: get rid of this
-void Layer::setToken(int32_t token)
+status_t Layer::setToken(const sp<UserClient>& userClient,
+ SharedClient* sharedClient, int32_t token)
{
- sp<Client> ourClient(client.promote());
-
- mToken = token;
-
- // no OpenGL operation is possible here, since we might not be
- // in the OpenGL thread.
- lcblk = new SharedBufferServer(
- ourClient->ctrlblk, token, mBufferManager.getDefaultBufferCount(),
+ SharedBufferServer* lcblk = new SharedBufferServer(
+ sharedClient, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
- mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
+ status_t err = mUserClientRef.setToken(userClient, lcblk, token);
+ if (err != NO_ERROR) {
+ LOGE("ClientRef::setToken(%p, %p, %u) failed",
+ userClient.get(), lcblk, token);
+ delete lcblk;
+ }
+
+ return err;
+}
+
+int32_t Layer::getToken() const
+{
+ return mUserClientRef.getToken();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
// wake up the condition
lcblk->setStatus(NO_INIT);
}
@@ -237,10 +247,9 @@
status_t Layer::setBufferCount(int bufferCount)
{
- // Ensures our client doesn't go away while we're accessing
- // the shared area.
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// oops, the client is already gone
return DEAD_OBJECT;
}
@@ -259,7 +268,7 @@
{
sp<GraphicBuffer> buffer;
- if ((reqWidth | reqHeight | reqFormat) < 0)
+ if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
return buffer;
if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
@@ -267,8 +276,9 @@
// this ensures our client doesn't go away while we're accessing
// the shared area.
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// oops, the client is already gone
return buffer;
}
@@ -403,8 +413,9 @@
// a buffer, it'll get the new size.
setBufferSize(temp.requested_w, temp.requested_h);
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
// all buffers need reallocation
lcblk->reallocateAll();
}
@@ -442,8 +453,9 @@
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- sp<Client> ourClient(client.promote());
- if (ourClient == 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (!lcblk) {
// client died
recomputeVisibleRegions = true;
return;
@@ -458,14 +470,14 @@
}
if (buf < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", buf);
+ LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
return;
}
// we retired a buffer, which becomes the new front buffer
if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
- LOGE("retireAndLock() buffer index (%d) out of range", buf);
+ LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
mPostedDirtyRegion.clear();
return;
}
@@ -560,11 +572,16 @@
void Layer::finishPageFlip()
{
- sp<Client> ourClient(client.promote());
- if (ourClient != 0) {
+ ClientRef::Access sharedClient(mUserClientRef);
+ SharedBufferServer* lcblk(sharedClient.get());
+ if (lcblk) {
int buf = mBufferManager.getActiveBufferIndex();
- status_t err = lcblk->unlock( buf );
- LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
+ if (buf >= 0) {
+ status_t err = lcblk->unlock( buf );
+ LOGE_IF(err!=NO_ERROR,
+ "layer %p, buffer=%d wasn't locked!",
+ this, buf);
+ }
}
}
@@ -573,8 +590,15 @@
{
LayerBaseClient::dump(result, buffer, SIZE);
- SharedBufferStack::Statistics stats = lcblk->getStats();
- result.append( lcblk->dump(" ") );
+ 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;
@@ -593,18 +617,59 @@
" "
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
" freezeLock=%p, dq-q-time=%u us\n",
- pixelFormat(),
- w0, h0, s0, w1, h1, s1,
- getFreezeLock().get(), stats.totalTime);
+ mFormat, w0, h0, s0, w1, h1, s1,
+ getFreezeLock().get(), totalTime);
result.append(buffer);
}
// ---------------------------------------------------------------------------
+Layer::ClientRef::ClientRef()
+ : mToken(-1) {
+}
+
+Layer::ClientRef::~ClientRef() {
+ delete lcblk;
+}
+
+int32_t Layer::ClientRef::getToken() const {
+ Mutex::Autolock _l(mLock);
+ return mToken;
+}
+
+status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
+ SharedBufferServer* sharedClient, int32_t token) {
+ Mutex::Autolock _l(mLock);
+ if (mToken >= 0)
+ return INVALID_OPERATION;
+ mUserClient = uc;
+ mToken = token;
+ lcblk = 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)
+ : lcblk(0)
+{
+ Mutex::Autolock _l(ref.mLock);
+ mUserClientStrongRef = ref.mUserClient.promote();
+ if (mUserClientStrongRef != 0)
+ lcblk = ref.lcblk;
+}
+
+// ---------------------------------------------------------------------------
+
Layer::BufferManager::BufferManager(TextureManager& tm)
: mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
- mActiveBuffer(0), mFailover(false)
+ mActiveBuffer(-1), mFailover(false)
{
}
@@ -625,7 +690,6 @@
}
status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
- // TODO: need to validate 'index'
mActiveBuffer = index;
return NO_ERROR;
}
@@ -636,7 +700,7 @@
Texture Layer::BufferManager::getActiveTexture() const {
Texture res;
- if (mFailover) {
+ if (mFailover || mActiveBuffer<0) {
res = mFailoverTexture;
} else {
static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
@@ -645,10 +709,14 @@
}
sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
- const size_t activeBuffer = mActiveBuffer;
- BufferData const * const buffers = mBufferData;
- Mutex::Autolock _l(mLock);
- return buffers[activeBuffer].buffer;
+ sp<GraphicBuffer> result;
+ const ssize_t activeBuffer = mActiveBuffer;
+ if (activeBuffer >= 0) {
+ BufferData const * const buffers = mBufferData;
+ Mutex::Autolock _l(mLock);
+ result = buffers[activeBuffer].buffer;
+ }
+ return result;
}
sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
@@ -692,19 +760,22 @@
status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
const sp<GraphicBuffer>& buffer)
{
- size_t index = mActiveBuffer;
- Image& texture(mBufferData[index].texture);
- status_t 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);
+ status_t err = NO_INIT;
+ ssize_t index = mActiveBuffer;
+ if (index >= 0) {
+ 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);
+ }
}
}
return err;
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index b427576..d396ecf 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -38,6 +38,7 @@
// ---------------------------------------------------------------------------
class Client;
+class UserClient;
class FreezeLock;
// ---------------------------------------------------------------------------
@@ -45,21 +46,26 @@
class Layer : public LayerBaseClient
{
public:
- // lcblk is (almost) only accessed from the main SF thread, in the places
- // where it's not, a reference to Client must be held
- SharedBufferServer* lcblk;
+ Layer(SurfaceFlinger* flinger, DisplayID display,
+ const sp<Client>& client);
- Layer(SurfaceFlinger* flinger, DisplayID display,
- const sp<Client>& client);
+ virtual ~Layer();
- virtual ~Layer();
+ virtual const char* getTypeId() const { return "Layer"; }
+ // the this layer's size and format
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;
+
+ // Set this Layer's buffers size
void setBufferSize(uint32_t w, uint32_t h);
bool isFixedSize() const;
+ // LayerBase interface
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
virtual void lockPageFlip(bool& recomputeVisibleRegions);
@@ -72,28 +78,26 @@
virtual sp<Surface> createSurface() const;
virtual status_t ditch();
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; }
- // only for debugging
- inline PixelFormat pixelFormat() const { return mFormat; }
- virtual const char* getTypeId() const { return "Layer"; }
+ // 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; }
protected:
virtual void dump(String8& result, char* scratch, size_t size) const;
private:
void reloadTexture(const Region& dirty);
-
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);
@@ -107,93 +111,120 @@
}
};
friend class SurfaceLayer;
-
- sp<Surface> mSurface;
- bool mSecure;
- int32_t mFrontBufferIndex;
- bool mNeedsBlending;
- bool mNeedsDithering;
- Region mPostedDirtyRegion;
- sp<FreezeLock> mFreezeLock;
- PixelFormat mFormat;
+ // -----------------------------------------------------------------------
- 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 mActiveBuffer;
- bool mFailover;
- static status_t destroyTexture(Image* tex, EGLDisplay dpy);
+ class ClientRef {
+ ClientRef(const ClientRef& rhs);
+ ClientRef& operator = (const ClientRef& rhs);
+ mutable Mutex mLock;
+ // binder thread, page-flip thread
+ SharedBufferServer* lcblk;
+ wp<UserClient> mUserClient;
+ int32_t mToken;
+ public:
+ ClientRef();
+ ~ClientRef();
+ int32_t getToken() const;
+ status_t setToken(const sp<UserClient>& uc,
+ SharedBufferServer* sharedClient, int32_t token);
+ sp<UserClient> getUserClientUnsafe() const;
+ class Access {
+ Access(const Access& rhs);
+ Access& operator = (const Access& rhs);
+ sp<UserClient> mUserClientStrongRef;
+ SharedBufferServer* lcblk;
+ public:
+ Access(const ClientRef& ref);
+ inline SharedBufferServer* get() const { return lcblk; }
+ };
+ friend class Access;
+ };
- 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);
+ 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 mActiveBuffer;
+ bool mFailover;
+ static status_t destroyTexture(Image* tex, EGLDisplay dpy);
- // resize the number of active buffers
- status_t resize(size_t size);
+ public:
+ static size_t getDefaultBufferCount() { return NUM_BUFFERS; }
+ BufferManager(TextureManager& tm);
+ ~BufferManager();
- // ----------------------------------------------
- // must be called from GL thread
+ // 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);
- // set/get active buffer index
- status_t setActiveBufferIndex(size_t index);
- size_t getActiveBufferIndex() const;
+ // ----------------------------------------------
+ // must be called from GL thread
- // return the active buffer
- sp<GraphicBuffer> getActiveBuffer() const;
+ // set/get active buffer index
+ status_t setActiveBufferIndex(size_t index);
+ size_t getActiveBufferIndex() const;
+ // return the active buffer
+ sp<GraphicBuffer> getActiveBuffer() 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);
- // return the active texture (or fail-over)
- Texture getActiveTexture() const;
+ // ----------------------------------------------
+ // only for debugging
+ sp<GraphicBuffer> getBuffer(size_t index) 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);
+ // thread-safe
+ ClientRef mUserClientRef;
- // make active buffer an EGLImage if needed
- status_t initEglImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& buffer);
+ // constants
+ sp<Surface> mSurface;
+ PixelFormat mFormat;
+ bool mNeedsBlending;
+ bool mNeedsDithering;
- // ----------------------------------------------
- // only for debugging
- sp<GraphicBuffer> getBuffer(size_t index) const;
- };
+ // page-flip thread (currently main thread)
+ bool mSecure;
+ Region mPostedDirtyRegion;
- TextureManager mTextureManager;
- BufferManager mBufferManager;
+ // page-flip thread and transaction thread (currently main thread)
+ sp<FreezeLock> mFreezeLock;
- // this lock protects mWidth and mHeight which are accessed from
- // the main thread and requestBuffer's binder transaction thread.
- mutable Mutex mLock;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mReqWidth;
- uint32_t mReqHeight;
- uint32_t mReqFormat;
- bool mFixedSize;
+ // see threading usage in declaration
+ TextureManager mTextureManager;
+ BufferManager mBufferManager;
- // TODO: get rid of this
-private:
- virtual void setToken(int32_t token);
- virtual int32_t getToken() const { return mToken; }
- int32_t mToken;
+ // binder thread, transaction thread
+ mutable Mutex mLock;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mReqWidth;
+ uint32_t mReqHeight;
+ uint32_t mReqFormat;
+ bool mFixedSize;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 80b001e..1f66fd0 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -151,7 +151,6 @@
return true;
}
bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) {
- // TODO: check the matrix has changed
mCurrentState.sequence++;
mCurrentState.transform.set(
matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
@@ -159,7 +158,6 @@
return true;
}
bool LayerBase::setTransparentRegionHint(const Region& transparent) {
- // TODO: check the region has changed
mCurrentState.sequence++;
mCurrentState.transparentRegion = transparent;
requestTransaction();
@@ -489,16 +487,16 @@
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client)
- : LayerBase(flinger, display), client(client),
+ : LayerBase(flinger, display), mClientRef(client),
mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
}
LayerBaseClient::~LayerBaseClient()
{
- sp<Client> c(client.promote());
+ sp<Client> c(mClientRef.promote());
if (c != 0) {
- c->free(this);
+ c->detachLayer(this);
}
}
@@ -524,7 +522,7 @@
{
LayerBase::dump(result, buffer, SIZE);
- sp<Client> client(this->client.promote());
+ sp<Client> client(mClientRef.promote());
snprintf(buffer, SIZE,
" name=%s\n"
" client=%p, identity=%u\n",
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index c9a516f..1a07f32 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -45,6 +45,7 @@
class Client;
class GraphicBuffer;
class GraphicPlane;
+class LayerBaseClient;
class SurfaceFlinger;
class Texture;
@@ -100,6 +101,8 @@
void invalidate();
+ virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
+
virtual const char* getTypeId() const { return "LayerBase"; }
/**
@@ -268,14 +271,14 @@
public:
class Surface;
- const wp<Client> client;
-
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client);
virtual ~LayerBaseClient();
sp<Surface> getSurface();
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; }
@@ -318,14 +321,10 @@
private:
mutable Mutex mLock;
mutable wp<Surface> mClientSurface;
+ const wp<Client> mClientRef;
// only read
const uint32_t mIdentity;
static int32_t sIdentity;
-
- // TODO: get rid of this
-public:
- virtual void setToken(int32_t token) { }
- virtual int32_t getToken() const { return -1; }
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index e8d0d5b..0f73774 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -236,6 +236,18 @@
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;
+}
+
+
const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
{
LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
@@ -772,7 +784,8 @@
void SurfaceFlinger::handlePageFlip()
{
bool visibleRegions = mVisibleRegionsDirty;
- LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
+ LayerVector& currentLayers = const_cast<LayerVector&>(
+ mDrawingState.layersSortedByZ);
visibleRegions |= lockPageFlip(currentLayers);
const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -794,7 +807,7 @@
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer = layers[i];
+ const sp<LayerBase>& layer(layers[i]);
layer->lockPageFlip(recomputeVisibleRegions);
}
return recomputeVisibleRegions;
@@ -807,7 +820,7 @@
size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer = layers[i];
+ const sp<LayerBase>& layer(layers[i]);
layer->unlockPageFlip(planeTransform, mDirtyRegion);
}
}
@@ -839,7 +852,7 @@
// takes a rectangle, we must make sure to update that whole
// rectangle in that case
if (flags & DisplayHardware::SWAP_RECTANGLE) {
- // FIXME: we really should be able to pass a region to
+ // TODO: we really should be able to pass a region to
// SWAP_RECTANGLE so that we don't have to redraw all this.
mDirtyRegion.set(mInvalidRegion.bounds());
} else {
@@ -1060,6 +1073,10 @@
status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
{
+ sp<LayerBaseClient> lbc(layerBase->getLayerBaseClient());
+ if (lbc != 0) {
+ mLayerMap.removeItem( lbc->getSurface()->asBinder() );
+ }
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
if (index >= 0) {
mLayersRemoved = true;
@@ -1192,12 +1209,14 @@
}
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
+ sp<Layer> normalLayer;
switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
layer = createPushBuffersSurface(client, d, w, h, flags);
} else {
- layer = createNormalSurface(client, d, w, h, flags, format);
+ normalLayer = createNormalSurface(client, d, w, h, flags, format);
+ layer = normalLayer;
}
break;
case eFXSurfaceBlur:
@@ -1212,6 +1231,7 @@
layer->initStates(w, h, flags);
layer->setName(name);
ssize_t token = addClientLayer(client, layer);
+
surfaceHandle = layer->getSurface();
if (surfaceHandle != 0) {
params->token = token;
@@ -1219,14 +1239,19 @@
params->width = w;
params->height = h;
params->format = format;
+ if (normalLayer != 0) {
+ Mutex::Autolock _l(mStateLock);
+ mLayerMap.add(surfaceHandle->asBinder(), normalLayer);
+ }
}
+
setTransactionFlags(eTransactionNeeded);
}
return surfaceHandle;
}
-sp<LayerBaseClient> SurfaceFlinger::createNormalSurface(
+sp<Layer> SurfaceFlinger::createNormalSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format)
@@ -1251,7 +1276,7 @@
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createBlurSurface(
+sp<LayerBlur> SurfaceFlinger::createBlurSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags)
{
@@ -1260,7 +1285,7 @@
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createDimSurface(
+sp<LayerDim> SurfaceFlinger::createDimSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags)
{
@@ -1269,7 +1294,7 @@
return layer;
}
-sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurface(
+sp<LayerBuffer> SurfaceFlinger::createPushBuffersSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags)
{
@@ -1567,32 +1592,24 @@
}
// ---------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#endif
+
+sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const
+{
+ sp<Layer> result;
+ Mutex::Autolock _l(mStateLock);
+ result = mLayerMap.valueFor( sur->asBinder() ).promote();
+ return result;
+}
+
+// ---------------------------------------------------------------------------
Client::Client(const sp<SurfaceFlinger>& flinger)
- : ctrlblk(0), mBitmap(0), mFlinger(flinger)
+ : mFlinger(flinger), mNameGenerator(1)
{
- 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;
- }
-
}
Client::~Client()
{
- if (ctrlblk) {
- ctrlblk->~SharedClient(); // destroy our shared-structure.
- }
-
const size_t count = mLayers.size();
for (size_t i=0 ; i<count ; i++) {
sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
@@ -1603,32 +1620,18 @@
}
status_t Client::initCheck() const {
- return ctrlblk == 0 ? NO_INIT : NO_ERROR;
+ return NO_ERROR;
}
ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{
- // TODO: get rid of this
- int32_t name = 0;
- while (mBitmap & (1LU<<name)) {
- name++;
- if (name >= 31)
- return NO_MEMORY;
- }
- mBitmap |= 1LU<<name;
- layer->setToken(name);
+ int32_t name = android_atomic_inc(&mNameGenerator);
mLayers.add(name, layer);
return name;
}
-void Client::free(LayerBaseClient const* layer)
+void Client::detachLayer(const LayerBaseClient* layer)
{
- // TODO: get rid of this
- int32_t name = layer->getToken();
- if (name >= 0) {
- mBitmap &= ~(1LU<<name);
- }
-
// we do a linear search here, because this doesn't happen often
const size_t count = mLayers.size();
for (size_t i=0 ; i<count ; i++) {
@@ -1649,12 +1652,15 @@
}
sp<IMemoryHeap> Client::getControlBlock() const {
- return mCblkHeap;
+ return 0;
+}
+ssize_t Client::getTokenForSurface(const sp<ISurface>& sur) const {
+ return -1;
}
sp<ISurface> Client::createSurface(
- ISurfaceComposerClient::surface_data_t* params,
- int pid, const String8& name,
- DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
+ ISurfaceComposerClient::surface_data_t* params, int pid,
+ const String8& name,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags)
{
return mFlinger->createSurface(this, pid, name, params,
@@ -1669,6 +1675,100 @@
// ---------------------------------------------------------------------------
+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.
+ */
+}
+
+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) {
+ android_atomic_and(~(1LU<<name), &mBitmap);
+ }
+}
+
+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;
+
+ // this layer already has a token, just return it
+ // FIXME: we should check that this token is for the same client
+ name = layer->getToken();
+ if (name >= 0) return name;
+
+ name = 0;
+ do {
+ int32_t mask = 1LU<<name;
+ if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
+ // we found and locked that name
+ layer->setToken(const_cast<UserClient*>(this), ctrlblk, name);
+ break;
+ }
+ if (++name > 31)
+ name = NO_MEMORY;
+ } while(name >= 0);
+
+ //LOGD("getTokenForSurface(%p) => %d", sur->asBinder().get(), name);
+ return name;
+}
+
+sp<ISurface> UserClient::createSurface(
+ ISurfaceComposerClient::surface_data_t* params, int pid,
+ const String8& name,
+ DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags) {
+ return 0;
+}
+status_t UserClient::destroySurface(SurfaceID sid) {
+ return INVALID_OPERATION;
+}
+status_t UserClient::setState(int32_t count, const layer_state_t* states) {
+ return INVALID_OPERATION;
+}
+
+// ---------------------------------------------------------------------------
+
GraphicPlane::GraphicPlane()
: mHw(0)
{
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 84134e0..0bfc170 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,8 @@
class DisplayHardware;
class FreezeLock;
class Layer;
+class LayerBlur;
+class LayerDim;
class LayerBuffer;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@@ -60,10 +62,6 @@
class Client : public BnSurfaceComposerClient
{
public:
- // pointer to this client's control block
- SharedClient* ctrlblk;
-
-public:
Client(const sp<SurfaceFlinger>& flinger);
~Client();
@@ -71,13 +69,14 @@
// protected by SurfaceFlinger::mStateLock
ssize_t attachLayer(const sp<LayerBaseClient>& layer);
+ void detachLayer(const LayerBaseClient* layer);
sp<LayerBaseClient> getLayerUser(int32_t i) const;
- void free(LayerBaseClient const* 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, int pid, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
@@ -85,8 +84,41 @@
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
- uint32_t mBitmap;
DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+ sp<SurfaceFlinger> mFlinger;
+ int32_t mNameGenerator;
+};
+
+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, int pid, 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;
};
@@ -152,6 +184,7 @@
// ISurfaceComposer interface
virtual sp<ISurfaceComposerClient> createConnection();
+ virtual sp<ISurfaceComposerClient> createClientConnection();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
virtual void openGlobalTransaction();
@@ -166,11 +199,12 @@
overlay_control_device_t* getOverlayEngine() const;
-
status_t removeLayer(const sp<LayerBase>& layer);
status_t addLayer(const sp<LayerBase>& layer);
status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
-
+
+ sp<Layer> getLayer(const sp<ISurface>& sur) const;
+
private:
friend class Client;
friend class LayerBase;
@@ -187,20 +221,20 @@
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags);
- sp<LayerBaseClient> createNormalSurface(
+ sp<Layer> createNormalSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format);
- sp<LayerBaseClient> createBlurSurface(
+ sp<LayerBlur> createBlurSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);
- sp<LayerBaseClient> createDimSurface(
+ sp<LayerDim> createDimSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);
- sp<LayerBaseClient> createPushBuffersSurface(
+ sp<LayerBuffer> createPushBuffersSurface(
const sp<Client>& client, DisplayID display,
uint32_t w, uint32_t h, uint32_t flags);
@@ -307,8 +341,7 @@
status_t postMessageSync(const sp<MessageBase>& msg,
nsecs_t reltime=0, uint32_t flags = 0);
-
-
+
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState;
@@ -321,6 +354,7 @@
// protected by mStateLock (but we could use another lock)
GraphicPlane mGraphicPlanes[1];
bool mLayersRemoved;
+ DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayerMap;
// constant members (no synchronization needed for access)
sp<IMemoryHeap> mServerHeap;
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 50495c1..5c111f6 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -55,6 +55,15 @@
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<IMemoryHeap> getCblk() const
{
Parcel data, reply;
@@ -136,6 +145,11 @@
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 OPEN_GLOBAL_TRANSACTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
openGlobalTransaction();
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
index 67c7df81..2cc1f8e 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
@@ -51,6 +51,7 @@
enum {
GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+ GET_TOKEN,
CREATE_SURFACE,
DESTROY_SURFACE,
SET_STATE
@@ -72,6 +73,15 @@
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,
int pid,
const String8& name,
@@ -132,6 +142,13 @@
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
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8d03145..1dd8642 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -58,7 +58,7 @@
void SharedBufferStack::init(int32_t i)
{
- inUse = -1;
+ inUse = -2;
status = NO_ERROR;
identity = i;
}
@@ -282,8 +282,10 @@
}
ssize_t SharedBufferServer::UnlockUpdate::operator()() {
if (stack.inUse != lockedBuffer) {
- LOGE("unlocking %d, but currently locked buffer is %d",
- lockedBuffer, stack.inUse);
+ LOGE("unlocking %d, but currently locked buffer is %d "
+ "(identity=%d, token=%d)",
+ lockedBuffer, stack.inUse,
+ stack.identity, stack.token);
return BAD_VALUE;
}
android_atomic_write(-1, &stack.inUse);
@@ -480,6 +482,7 @@
mNumBuffers(num)
{
mSharedStack->init(identity);
+ mSharedStack->token = surface;
mSharedStack->head = num-1;
mSharedStack->available = num;
mSharedStack->queued = 0;
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index ac4b198..01420fe 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -238,14 +238,12 @@
{
uint32_t flags = 0;
uint32_t format = 0;
- SurfaceID token = -1;
uint32_t identity = 0;
uint32_t width = 0;
uint32_t height = 0;
sp<SurfaceComposerClient> client;
sp<ISurface> sur;
if (SurfaceControl::isValid(control)) {
- token = control->mToken;
identity = control->mIdentity;
client = control->mClient;
sur = control->mSurface;
@@ -254,9 +252,7 @@
format = control->mFormat;
flags = control->mFlags;
}
- parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
- parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
- parcel->writeInt32(token);
+ parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(identity);
parcel->writeInt32(width);
parcel->writeInt32(height);
@@ -278,31 +274,78 @@
// 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)
- : mSurface(surface->mSurface),
- mToken(surface->mToken), mIdentity(surface->mIdentity),
- mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
+ : mBufferMapper(GraphicBufferMapper::get()),
+ mClient(SurfaceClient::getInstance()),
+ mSharedBufferClient(NULL),
mInitCheck(NO_INIT),
+ mSurface(surface->mSurface),
+ mIdentity(surface->mIdentity),
+ mFormat(surface->mFormat), mFlags(surface->mFlags),
mWidth(surface->mWidth), mHeight(surface->mHeight)
{
- mClient = new SurfaceClient(surface->mClient);
init();
}
Surface::Surface(const Parcel& parcel)
- : mBufferMapper(GraphicBufferMapper::get()),
- mSharedBufferClient(NULL), mInitCheck(NO_INIT)
+ : mBufferMapper(GraphicBufferMapper::get()),
+ mClient(SurfaceClient::getInstance()),
+ mSharedBufferClient(NULL),
+ mInitCheck(NO_INIT)
{
- sp<IBinder> conn = parcel.readStrongBinder();
mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
- mToken = parcel.readInt32();
mIdentity = parcel.readInt32();
mWidth = parcel.readInt32();
mHeight = parcel.readInt32();
mFormat = parcel.readInt32();
mFlags = parcel.readInt32();
- mClient = new SurfaceClient(conn);
init();
}
@@ -330,12 +373,14 @@
mBuffers.setCapacity(2);
mBuffers.insertAt(0, 2);
- if (mClient != 0 && mClient->initCheck() == NO_ERROR) {
- mSharedBufferClient = new SharedBufferClient(
- mClient->getSharedClient(), mToken, 2, mIdentity);
+ if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
+ mToken = mClient.getTokenForSurface(mSurface);
+ if (mToken >= 0) {
+ mSharedBufferClient = new SharedBufferClient(
+ mClient.getSharedClient(), mToken, 2, mIdentity);
+ mInitCheck = mClient.getSharedClient()->validate(mToken);
+ }
}
-
- mInitCheck = initCheck();
}
Surface::~Surface()
@@ -352,25 +397,11 @@
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
mBuffers.clear();
- mClient.clear();
mSurface.clear();
delete mSharedBufferClient;
IPCThreadState::self()->flushCommands();
}
-status_t Surface::initCheck() const
-{
- if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) {
- return NO_INIT;
- }
- SharedClient const* cblk = mClient->getSharedClient();
- if (cblk == 0) {
- LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
- return NO_INIT;
- }
- return cblk->validate(mToken);
-}
-
bool Surface::isValid() {
return mInitCheck == NO_ERROR;
}
@@ -379,8 +410,7 @@
{
// check that we initialized ourself properly
if (mInitCheck != NO_ERROR) {
- LOGE("invalid token (%d, identity=%u) or client (%p)",
- mToken, mIdentity, mClient.get());
+ LOGE("invalid token (%d, identity=%u)", mToken, mIdentity);
return mInitCheck;
}
@@ -558,8 +588,8 @@
LOGE_IF(err, "error queuing buffer %d (%s)", bufIdx, strerror(-err));
if (err == NO_ERROR) {
- // FIXME: can we avoid this IPC if we know there is one pending?
- mClient->signalServer();
+ // TODO: can we avoid this IPC if we know there is one pending?
+ mClient.signalServer();
}
return err;
}
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index 0670d20..5ac0d5d 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -42,36 +42,26 @@
namespace android {
// ---------------------------------------------------------------------------
-class ComposerService : public Singleton<ComposerService>
-{
- // these are constants
- sp<ISurfaceComposer> mComposerService;
- sp<IMemoryHeap> mServerCblkMemory;
- surface_flinger_cblk_t volatile* mServerCblk;
-
- ComposerService() : Singleton<ComposerService>() {
- const String16 name("SurfaceFlinger");
- while (getService(name, &mComposerService) != NO_ERROR) {
- usleep(250000);
- }
- mServerCblkMemory = mComposerService->getCblk();
- mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
- mServerCblkMemory->getBase());
- }
-
- friend class Singleton<ComposerService>;
-
-public:
- static sp<ISurfaceComposer> getComposerService() {
- return ComposerService::getInstance().mComposerService;
- }
- static surface_flinger_cblk_t const volatile * getControlBlock() {
- return ComposerService::getInstance().mServerCblk;
- }
-};
-
ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
+ComposerService::ComposerService()
+: Singleton<ComposerService>() {
+ const String16 name("SurfaceFlinger");
+ while (getService(name, &mComposerService) != NO_ERROR) {
+ usleep(250000);
+ }
+ mServerCblkMemory = mComposerService->getCblk();
+ mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
+ mServerCblkMemory->getBase());
+}
+
+sp<ISurfaceComposer> ComposerService::getComposerService() {
+ return ComposerService::getInstance().mComposerService;
+}
+
+surface_flinger_cblk_t const volatile * ComposerService::getControlBlock() {
+ return ComposerService::getInstance().mServerCblk;
+}
static inline sp<ISurfaceComposer> getComposerService() {
return ComposerService::getComposerService();
@@ -557,41 +547,5 @@
}
// ----------------------------------------------------------------------------
-
-SurfaceClient::SurfaceClient(const sp<SurfaceComposerClient>& client)
- : mStatus(NO_INIT), mControl(0)
-{
- if (client != 0) {
- sp<IBinder> conn = client->connection();
- init(conn);
- }
-}
-SurfaceClient::SurfaceClient(const sp<IBinder>& conn)
- : mStatus(NO_INIT), mControl(0)
-{
- init(conn);
-}
-void SurfaceClient::init(const sp<IBinder>& conn)
-{
- mComposerService = getComposerService();
- sp<ISurfaceComposerClient> sf(interface_cast<ISurfaceComposerClient>(conn));
- if (sf != 0) {
- mConnection = conn;
- mControlMemory = sf->getControlBlock();
- mControl = static_cast<SharedClient *>(mControlMemory->getBase());
- mStatus = NO_ERROR;
- }
-}
-status_t SurfaceClient::initCheck() const {
- return mStatus;
-}
-SharedClient* SurfaceClient::getSharedClient() const {
- return mControl;
-}
-void SurfaceClient::signalServer() const {
- mComposerService->signal();
-}
-
-// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 35e4af3..3ddde38 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -38,7 +38,7 @@
GraphicBuffer::GraphicBuffer()
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
+ mInitCheck(NO_ERROR), mIndex(-1)
{
width =
height =
@@ -51,7 +51,7 @@
GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
PixelFormat reqFormat, uint32_t reqUsage)
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
+ mInitCheck(NO_ERROR), mIndex(-1)
{
width =
height =
@@ -67,7 +67,7 @@
uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
+ mInitCheck(NO_ERROR), mIndex(-1)
{
width = w;
height = h;
@@ -141,7 +141,6 @@
this->height = h;
this->format = format;
this->usage = reqUsage;
- mVStride = 0;
}
return err;
}
@@ -182,7 +181,6 @@
sur->height = height;
sur->stride = stride;
sur->format = format;
- sur->vstride = mVStride;
sur->data = static_cast<GGLubyte*>(vaddr);
}
return res;
@@ -276,14 +274,6 @@
return mIndex;
}
-void GraphicBuffer::setVerticalStride(uint32_t vstride) {
- mVStride = vstride;
-}
-
-uint32_t GraphicBuffer::getVerticalStride() const {
- return mVStride;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android