Loading services/surfaceflinger/Layer.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,18 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const return sur; } status_t Layer::ditch() { // NOTE: Called from the main UI thread // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; return NO_ERROR; } status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { Loading services/surfaceflinger/Layer.h +1 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ public: virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); // only for debugging Loading services/surfaceflinger/LayerBase.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -616,7 +616,10 @@ LayerBaseClient::Surface::~Surface() */ // destroy client resources mFlinger->destroySurface(mOwner); sp<LayerBaseClient> layer = getOwner(); if (layer != 0) { mFlinger->destroySurface(layer); } } sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { Loading services/surfaceflinger/LayerBase.h +5 −2 Original line number Diff line number Diff line Loading @@ -202,6 +202,10 @@ public: */ virtual bool isProtected() const { return false; } /** Called from the main thread, when the surface is removed from the * draw list */ virtual status_t ditch() { return NO_ERROR; } /** called with the state lock when the surface is removed from the * current list */ virtual void onRemoved() { }; Loading Loading @@ -267,8 +271,7 @@ protected: volatile int32_t mInvalidate; public: // called from class SurfaceFlinger protected: virtual ~LayerBase(); private: Loading services/surfaceflinger/SurfaceFlinger.cpp +81 −51 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ bool SurfaceFlinger::threadLoop() if (LIKELY(mTransactionCount == 0)) { // if we're in a global transaction, don't do anything. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; uint32_t transactionFlags = peekTransactionFlags(mask); uint32_t transactionFlags = getTransactionFlags(mask); if (LIKELY(transactionFlags)) { handleTransaction(transactionFlags); } Loading Loading @@ -480,26 +480,39 @@ void SurfaceFlinger::handleConsoleEvents() void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) { Vector< sp<LayerBase> > ditchedLayers; /* * Perform and commit the transaction */ { // scope for the lock Mutex::Autolock _l(mStateLock); const nsecs_t now = systemTime(); mDebugInTransaction = now; // Here we're guaranteed that some transaction flags are set // so we can call handleTransactionLocked() unconditionally. // We call getTransactionFlags(), which will also clear the flags, // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; transactionFlags = getTransactionFlags(mask); handleTransactionLocked(transactionFlags); handleTransactionLocked(transactionFlags, ditchedLayers); mLastTransactionTime = systemTime() - now; mDebugInTransaction = 0; invalidateHwcGeometry(); // here the transaction has been committed } void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) /* * Clean-up all layers that went away * (do this without the lock held) */ const size_t count = ditchedLayers.size(); for (size_t i=0 ; i<count ; i++) { if (ditchedLayers[i] != 0) { //LOGD("ditching layer %p", ditchedLayers[i].get()); ditchedLayers[i]->ditch(); } } } void SurfaceFlinger::handleTransactionLocked( uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers) { const LayerVector& currentLayers(mCurrentState.layersSortedByZ); const size_t count = currentLayers.size(); Loading Loading @@ -571,6 +584,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const sp<LayerBase>& layer(previousLayers[i]); if (currentLayers.indexOf( layer ) < 0) { // this layer is not visible anymore ditchedLayers.add(layer); mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen); } } Loading Loading @@ -1082,15 +1096,15 @@ status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<LayerBaseClient>& lbc) { // attach this layer to the client size_t name = client->attachLayer(lbc); Mutex::Autolock _l(mStateLock); // attach this layer to the client ssize_t name = client->attachLayer(lbc); // add this layer to the current state list addLayer_l(lbc); return ssize_t(name); return name; } status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) Loading Loading @@ -1141,11 +1155,6 @@ status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) return NO_ERROR; } uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags) { return android_atomic_release_load(&mTransactionFlags); } uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { return android_atomic_and(~flags, &mTransactionFlags) & flags; Loading Loading @@ -1353,26 +1362,51 @@ status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid) return err; } status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer) status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) { // called by ~ISurface() when all references are gone status_t err = NO_ERROR; sp<LayerBaseClient> l(layer.promote()); if (l != NULL) { Mutex::Autolock _l(mStateLock); err = removeLayer_l(l); class MessageDestroySurface : public MessageBase { SurfaceFlinger* flinger; sp<LayerBaseClient> layer; public: MessageDestroySurface( SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer) : flinger(flinger), layer(layer) { } virtual bool handler() { sp<LayerBaseClient> l(layer); layer.clear(); // clear it outside of the lock; Mutex::Autolock _l(flinger->mStateLock); /* * remove the layer from the current list -- chances are that it's * not in the list anyway, because it should have been removed * already upon request of the client (eg: window manager). * However, a buggy client could have not done that. * Since we know we don't have any more clients, we don't need * to use the purgatory. */ status_t err = flinger->removeLayer_l(l); if (err == NAME_NOT_FOUND) { // The surface wasn't in the current list, which means it was // removed already, which means it is in the purgatory, // and need to be removed from there. ssize_t idx = mLayerPurgatory.remove(l); // This needs to happen from the main thread since its dtor // must run from there (b/c of OpenGL ES). Additionally, we // can't really acquire our internal lock from // destroySurface() -- see postMessage() below. ssize_t idx = flinger->mLayerPurgatory.remove(l); LOGE_IF(idx < 0, "layer=%p is not in the purgatory list", l.get()); } LOGE_IF(err<0 && err != NAME_NOT_FOUND, "error removing layer=%p (%s)", l.get(), strerror(-err)); return true; } return err; }; postMessageAsync( new MessageDestroySurface(this, layer) ); return NO_ERROR; } status_t SurfaceFlinger::setClientState( Loading Loading @@ -2347,17 +2381,15 @@ status_t Client::initCheck() const { return NO_ERROR; } size_t Client::attachLayer(const sp<LayerBaseClient>& layer) ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer) { Mutex::Autolock _l(mLock); size_t name = mNameGenerator++; int32_t name = android_atomic_inc(&mNameGenerator); mLayers.add(name, layer); return name; } void Client::detachLayer(const LayerBaseClient* layer) { Mutex::Autolock _l(mLock); // 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++) { Loading @@ -2367,11 +2399,9 @@ void Client::detachLayer(const LayerBaseClient* layer) } } } sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { Mutex::Autolock _l(mLock); sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { sp<LayerBaseClient> lbc; wp<LayerBaseClient> layer(mLayers.valueFor(i)); const wp<LayerBaseClient>& layer(mLayers.valueFor(i)); if (layer != 0) { lbc = layer.promote(); LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i)); Loading Loading
services/surfaceflinger/Layer.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,18 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const return sur; } status_t Layer::ditch() { // NOTE: Called from the main UI thread // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; return NO_ERROR; } status_t Layer::setBuffers( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { Loading
services/surfaceflinger/Layer.h +1 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,7 @@ public: virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; virtual sp<Surface> createSurface() const; virtual status_t ditch(); virtual void onRemoved(); // only for debugging Loading
services/surfaceflinger/LayerBase.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -616,7 +616,10 @@ LayerBaseClient::Surface::~Surface() */ // destroy client resources mFlinger->destroySurface(mOwner); sp<LayerBaseClient> layer = getOwner(); if (layer != 0) { mFlinger->destroySurface(layer); } } sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { Loading
services/surfaceflinger/LayerBase.h +5 −2 Original line number Diff line number Diff line Loading @@ -202,6 +202,10 @@ public: */ virtual bool isProtected() const { return false; } /** Called from the main thread, when the surface is removed from the * draw list */ virtual status_t ditch() { return NO_ERROR; } /** called with the state lock when the surface is removed from the * current list */ virtual void onRemoved() { }; Loading Loading @@ -267,8 +271,7 @@ protected: volatile int32_t mInvalidate; public: // called from class SurfaceFlinger protected: virtual ~LayerBase(); private: Loading
services/surfaceflinger/SurfaceFlinger.cpp +81 −51 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ bool SurfaceFlinger::threadLoop() if (LIKELY(mTransactionCount == 0)) { // if we're in a global transaction, don't do anything. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; uint32_t transactionFlags = peekTransactionFlags(mask); uint32_t transactionFlags = getTransactionFlags(mask); if (LIKELY(transactionFlags)) { handleTransaction(transactionFlags); } Loading Loading @@ -480,26 +480,39 @@ void SurfaceFlinger::handleConsoleEvents() void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) { Vector< sp<LayerBase> > ditchedLayers; /* * Perform and commit the transaction */ { // scope for the lock Mutex::Autolock _l(mStateLock); const nsecs_t now = systemTime(); mDebugInTransaction = now; // Here we're guaranteed that some transaction flags are set // so we can call handleTransactionLocked() unconditionally. // We call getTransactionFlags(), which will also clear the flags, // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. const uint32_t mask = eTransactionNeeded | eTraversalNeeded; transactionFlags = getTransactionFlags(mask); handleTransactionLocked(transactionFlags); handleTransactionLocked(transactionFlags, ditchedLayers); mLastTransactionTime = systemTime() - now; mDebugInTransaction = 0; invalidateHwcGeometry(); // here the transaction has been committed } void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) /* * Clean-up all layers that went away * (do this without the lock held) */ const size_t count = ditchedLayers.size(); for (size_t i=0 ; i<count ; i++) { if (ditchedLayers[i] != 0) { //LOGD("ditching layer %p", ditchedLayers[i].get()); ditchedLayers[i]->ditch(); } } } void SurfaceFlinger::handleTransactionLocked( uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers) { const LayerVector& currentLayers(mCurrentState.layersSortedByZ); const size_t count = currentLayers.size(); Loading Loading @@ -571,6 +584,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const sp<LayerBase>& layer(previousLayers[i]); if (currentLayers.indexOf( layer ) < 0) { // this layer is not visible anymore ditchedLayers.add(layer); mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen); } } Loading Loading @@ -1082,15 +1096,15 @@ status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<LayerBaseClient>& lbc) { // attach this layer to the client size_t name = client->attachLayer(lbc); Mutex::Autolock _l(mStateLock); // attach this layer to the client ssize_t name = client->attachLayer(lbc); // add this layer to the current state list addLayer_l(lbc); return ssize_t(name); return name; } status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) Loading Loading @@ -1141,11 +1155,6 @@ status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) return NO_ERROR; } uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags) { return android_atomic_release_load(&mTransactionFlags); } uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { return android_atomic_and(~flags, &mTransactionFlags) & flags; Loading Loading @@ -1353,26 +1362,51 @@ status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid) return err; } status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer) status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) { // called by ~ISurface() when all references are gone status_t err = NO_ERROR; sp<LayerBaseClient> l(layer.promote()); if (l != NULL) { Mutex::Autolock _l(mStateLock); err = removeLayer_l(l); class MessageDestroySurface : public MessageBase { SurfaceFlinger* flinger; sp<LayerBaseClient> layer; public: MessageDestroySurface( SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer) : flinger(flinger), layer(layer) { } virtual bool handler() { sp<LayerBaseClient> l(layer); layer.clear(); // clear it outside of the lock; Mutex::Autolock _l(flinger->mStateLock); /* * remove the layer from the current list -- chances are that it's * not in the list anyway, because it should have been removed * already upon request of the client (eg: window manager). * However, a buggy client could have not done that. * Since we know we don't have any more clients, we don't need * to use the purgatory. */ status_t err = flinger->removeLayer_l(l); if (err == NAME_NOT_FOUND) { // The surface wasn't in the current list, which means it was // removed already, which means it is in the purgatory, // and need to be removed from there. ssize_t idx = mLayerPurgatory.remove(l); // This needs to happen from the main thread since its dtor // must run from there (b/c of OpenGL ES). Additionally, we // can't really acquire our internal lock from // destroySurface() -- see postMessage() below. ssize_t idx = flinger->mLayerPurgatory.remove(l); LOGE_IF(idx < 0, "layer=%p is not in the purgatory list", l.get()); } LOGE_IF(err<0 && err != NAME_NOT_FOUND, "error removing layer=%p (%s)", l.get(), strerror(-err)); return true; } return err; }; postMessageAsync( new MessageDestroySurface(this, layer) ); return NO_ERROR; } status_t SurfaceFlinger::setClientState( Loading Loading @@ -2347,17 +2381,15 @@ status_t Client::initCheck() const { return NO_ERROR; } size_t Client::attachLayer(const sp<LayerBaseClient>& layer) ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer) { Mutex::Autolock _l(mLock); size_t name = mNameGenerator++; int32_t name = android_atomic_inc(&mNameGenerator); mLayers.add(name, layer); return name; } void Client::detachLayer(const LayerBaseClient* layer) { Mutex::Autolock _l(mLock); // 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++) { Loading @@ -2367,11 +2399,9 @@ void Client::detachLayer(const LayerBaseClient* layer) } } } sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { Mutex::Autolock _l(mLock); sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { sp<LayerBaseClient> lbc; wp<LayerBaseClient> layer(mLayers.valueFor(i)); const wp<LayerBaseClient>& layer(mLayers.valueFor(i)); if (layer != 0) { lbc = layer.promote(); LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i)); Loading