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 /libs/surfaceflinger | |
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
Diffstat (limited to 'libs/surfaceflinger')
-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 |
6 files changed, 468 insertions, 235 deletions
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; |