diff options
author | Mathias Agopian <mathias@google.com> | 2010-06-01 15:12:58 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2010-06-04 18:57:41 -0700 |
commit | b7e930db175c192464cebdeb49eb56cf6dd60114 (patch) | |
tree | 15f475afd3e4d6462587368154f84623defd2776 | |
parent | 96f0819f81293076e652792794a961543e6750d7 (diff) | |
download | frameworks_native-b7e930db175c192464cebdeb49eb56cf6dd60114.zip frameworks_native-b7e930db175c192464cebdeb49eb56cf6dd60114.tar.gz frameworks_native-b7e930db175c192464cebdeb49eb56cf6dd60114.tar.bz2 |
split surface management from surface's buffers management
Change-Id: If3c5655d1231f8f0c49ba68f972b1b20c93b3f87
-rw-r--r-- | include/private/surfaceflinger/SharedBufferStack.h | 3 | ||||
-rw-r--r-- | include/surfaceflinger/ISurfaceComposer.h | 6 | ||||
-rw-r--r-- | include/surfaceflinger/ISurfaceComposerClient.h | 1 | ||||
-rw-r--r-- | include/surfaceflinger/Surface.h | 9 | ||||
-rw-r--r-- | include/surfaceflinger/SurfaceComposerClient.h | 38 | ||||
-rw-r--r-- | include/ui/GraphicBuffer.h | 13 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 187 | ||||
-rw-r--r-- | libs/surfaceflinger/Layer.h | 235 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.cpp | 10 | ||||
-rw-r--r-- | libs/surfaceflinger/LayerBase.h | 13 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.cpp | 196 | ||||
-rw-r--r-- | libs/surfaceflinger/SurfaceFlinger.h | 62 | ||||
-rw-r--r-- | libs/surfaceflinger_client/ISurfaceComposer.cpp | 14 | ||||
-rw-r--r-- | libs/surfaceflinger_client/ISurfaceComposerClient.cpp | 17 | ||||
-rw-r--r-- | libs/surfaceflinger_client/SharedBufferStack.cpp | 9 | ||||
-rw-r--r-- | libs/surfaceflinger_client/Surface.cpp | 106 | ||||
-rw-r--r-- | libs/surfaceflinger_client/SurfaceComposerClient.cpp | 78 | ||||
-rw-r--r-- | libs/ui/GraphicBuffer.cpp | 16 |
18 files changed, 629 insertions, 384 deletions
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 @@ public: 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 @@ public: /* 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 @@ public: // 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 @@ public: }; 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 @@ private: */ 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 @@ private: }; // 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 Region; 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 @@ private: }; // --------------------------------------------------------------------------- - -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 @@ public: 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 @@ protected: 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 @@ private: GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; - uint32_t mVStride; int mIndex; }; diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 85149f5..a94fdd4 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -50,10 +50,9 @@ template <typename T> inline T min(T a, T b) { 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 @@ Layer::~Layer() 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()); + SharedBufferServer* lcblk = new SharedBufferServer( + sharedClient, token, mBufferManager.getDefaultBufferCount(), + getIdentity()); - mToken = token; + 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; + } - // no OpenGL operation is possible here, since we might not be - // in the OpenGL thread. - lcblk = new SharedBufferServer( - ourClient->ctrlblk, token, mBufferManager.getDefaultBufferCount(), - getIdentity()); + return err; +} - mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); +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 @@ bool Layer::needsFiltering() const 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> Layer::requestBuffer(int index, { 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 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, // 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 @@ uint32_t Layer::doTransaction(uint32_t flags) // 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 @@ bool Layer::isFixedSize() const { 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 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) } 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::unlockPageFlip( 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 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const { 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 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const " " "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 @@ sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const { } status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { - // TODO: need to validate 'index' mActiveBuffer = index; return NO_ERROR; } @@ -636,7 +700,7 @@ size_t Layer::BufferManager::getActiveBufferIndex() const { 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 @@ Texture Layer::BufferManager::getActiveTexture() const { } 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::destroy(EGLDisplay dpy) 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 @@ namespace android { // --------------------------------------------------------------------------- class Client; +class UserClient; class FreezeLock; // --------------------------------------------------------------------------- @@ -45,21 +46,26 @@ class FreezeLock; 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 @@ public: 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; } + inline sp<GraphicBuffer> getBuffer(int i) const { + return mBufferManager.getBuffer(i); } // only for debugging - inline PixelFormat pixelFormat() const { return mFormat; } - - virtual const char* getTypeId() const { return "Layer"; } + 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 @@ private: } }; 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); - - 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); - - // ---------------------------------------------- - // 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 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; - }; - - TextureManager mTextureManager; - BufferManager mBufferManager; - - // 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; - - // TODO: get rid of this -private: - virtual void setToken(int32_t token); - virtual int32_t getToken() const { return mToken; } - int32_t mToken; + + // ----------------------------------------------------------------------- + + 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; + }; + + // ----------------------------------------------------------------------- + + 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); + + 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); + + // ---------------------------------------------- + // 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 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; + }; + + // ----------------------------------------------------------------------- + + // thread-safe + ClientRef mUserClientRef; + + // constants + sp<Surface> mSurface; + PixelFormat mFormat; + bool mNeedsBlending; + bool mNeedsDithering; + + // page-flip thread (currently main thread) + bool mSecure; + Region mPostedDirtyRegion; + + // 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 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 @@ bool LayerBase::setAlpha(uint8_t alpha) { 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 @@ bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) { return true; } bool LayerBase::setTransparentRegionHint(const Region& transparent) { - // TODO: check the region has changed mCurrentState.sequence++; mCurrentState.transparentRegion = transparent; requestTransaction(); @@ -489,16 +487,16 @@ int32_t LayerBaseClient::sIdentity = 1; 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 @@ void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const { 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 DisplayHardware; class Client; class GraphicBuffer; class GraphicPlane; +class LayerBaseClient; class SurfaceFlinger; class Texture; @@ -100,6 +101,8 @@ public: void invalidate(); + virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; } + virtual const char* getTypeId() const { return "LayerBase"; } /** @@ -268,14 +271,14 @@ class LayerBaseClient : public LayerBase 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 @@ protected: 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 @@ 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; +} + + const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const { LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy); @@ -772,7 +784,8 @@ void SurfaceFlinger::commitTransaction() 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 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) 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 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) 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 @@ void SurfaceFlinger::handleRepaint() // 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(const sp<LayerBase>& layer) 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 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, } //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 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, 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 @@ sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid, 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 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurface( 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 @@ sp<LayerBaseClient> SurfaceFlinger::createBlurSurface( 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 @@ sp<LayerBaseClient> SurfaceFlinger::createDimSurface( 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 @@ status_t SurfaceFlinger::onTransact( } // --------------------------------------------------------------------------- -#if 0 -#pragma mark - -#endif -Client::Client(const sp<SurfaceFlinger>& flinger) - : ctrlblk(0), mBitmap(0), mFlinger(flinger) +sp<Layer> SurfaceFlinger::getLayer(const sp<ISurface>& sur) const { - const int pgsize = getpagesize(); - const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1)); - - mCblkHeap = new MemoryHeapBase(cblksize, 0, - "SurfaceFlinger Client control-block"); + sp<Layer> result; + Mutex::Autolock _l(mStateLock); + result = mLayerMap.valueFor( sur->asBinder() ).promote(); + return result; +} - ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase()); - if (ctrlblk) { // construct the shared structure in-place. - new(ctrlblk) SharedClient; - } +// --------------------------------------------------------------------------- +Client::Client(const sp<SurfaceFlinger>& flinger) + : mFlinger(flinger), mNameGenerator(1) +{ } 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 @@ Client::~Client() } 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<LayerBaseClient> Client::getLayerUser(int32_t i) const { } 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 @@ status_t Client::setState(int32_t count, const layer_state_t* 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. + */ +} + +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 Client; 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 LayerBuffer; 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 @@ public: // 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 @@ private: 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 @@ public: // 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 @@ public: 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 @@ private: 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 @@ private: 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 @@ private: // 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 @@ 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<IMemoryHeap> getCblk() const { Parcel data, reply; @@ -136,6 +145,11 @@ 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 OPEN_GLOBAL_TRANSACTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); openGlobalTransaction(); diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp index 67c7df8..2cc1f8e 100644 --- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp @@ -51,6 +51,7 @@ namespace android { enum { GET_CBLK = IBinder::FIRST_CALL_TRANSACTION, + GET_TOKEN, CREATE_SURFACE, DESTROY_SURFACE, SET_STATE @@ -72,6 +73,15 @@ public: 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 @@ status_t BnSurfaceComposerClient::onTransact( 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 @@ SharedBufferStack::SharedBufferStack() void SharedBufferStack::init(int32_t i) { - inUse = -1; + inUse = -2; status = NO_ERROR; identity = i; } @@ -282,8 +282,10 @@ SharedBufferServer::UnlockUpdate::UnlockUpdate( } 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 @@ SharedBufferServer::SharedBufferServer(SharedClient* sharedClient, 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 @@ status_t SurfaceControl::writeSurfaceToParcel( { 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 @@ status_t SurfaceControl::writeSurfaceToParcel( 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 @@ 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) - : 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 @@ void Surface::init() 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 @@ 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(); - 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 @@ status_t Surface::validate() const { // 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 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) 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>; +ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); -public: - static sp<ISurfaceComposer> getComposerService() { - return ComposerService::getInstance().mComposerService; +ComposerService::ComposerService() +: Singleton<ComposerService>() { + const String16 name("SurfaceFlinger"); + while (getService(name, &mComposerService) != NO_ERROR) { + usleep(250000); } - static surface_flinger_cblk_t const volatile * getControlBlock() { - return ComposerService::getInstance().mServerCblk; - } -}; + mServerCblkMemory = mComposerService->getCblk(); + mServerCblk = static_cast<surface_flinger_cblk_t volatile *>( + mServerCblkMemory->getBase()); +} -ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService); +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 @@ status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) } // ---------------------------------------------------------------------------- - -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 @@ namespace android { 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() 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 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, 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 @@ status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format, this->height = h; this->format = format; this->usage = reqUsage; - mVStride = 0; } return err; } @@ -182,7 +181,6 @@ status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage) sur->height = height; sur->stride = stride; sur->format = format; - sur->vstride = mVStride; sur->data = static_cast<GGLubyte*>(vaddr); } return res; @@ -276,14 +274,6 @@ int GraphicBuffer::getIndex() const { return mIndex; } -void GraphicBuffer::setVerticalStride(uint32_t vstride) { - mVStride = vstride; -} - -uint32_t GraphicBuffer::getVerticalStride() const { - return mVStride; -} - // --------------------------------------------------------------------------- }; // namespace android |