Loading include/private/surfaceflinger/SharedBufferStack.h +29 −14 Original line number Original line Diff line number Diff line Loading @@ -55,12 +55,6 @@ namespace android { * * */ */ // When changing these values, the COMPILE_TIME_ASSERT at the end of this // file need to be updated. const unsigned int NUM_LAYERS_MAX = 31; const unsigned int NUM_BUFFER_MAX = 16; const unsigned int NUM_DISPLAY_MAX = 4; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- class Region; class Region; Loading @@ -82,6 +76,12 @@ class SharedBufferStack friend class SharedBufferServer; friend class SharedBufferServer; public: public: // When changing these values, the COMPILE_TIME_ASSERT at the end of this // file need to be updated. static const unsigned int NUM_LAYERS_MAX = 31; static const unsigned int NUM_BUFFER_MAX = 16; static const unsigned int NUM_DISPLAY_MAX = 4; struct Statistics { // 4 longs struct Statistics { // 4 longs typedef int32_t usecs_t; typedef int32_t usecs_t; usecs_t totalTime; usecs_t totalTime; Loading Loading @@ -147,7 +147,7 @@ private: // FIXME: this should be replaced by a lock-less primitive // FIXME: this should be replaced by a lock-less primitive Mutex lock; Mutex lock; Condition cv; Condition cv; SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ]; }; }; // ============================================================================ // ============================================================================ Loading @@ -155,7 +155,7 @@ private: class SharedBufferBase class SharedBufferBase { { public: public: SharedBufferBase(SharedClient* sharedClient, int surface, int num, SharedBufferBase(SharedClient* sharedClient, int surface, int32_t identity); int32_t identity); ~SharedBufferBase(); ~SharedBufferBase(); uint32_t getIdentity(); uint32_t getIdentity(); Loading @@ -166,9 +166,7 @@ public: protected: protected: SharedClient* const mSharedClient; SharedClient* const mSharedClient; SharedBufferStack* const mSharedStack; SharedBufferStack* const mSharedStack; int mNumBuffers; const int mIdentity; const int mIdentity; int32_t computeTail() const; friend struct Update; friend struct Update; friend struct QueueUpdate; friend struct QueueUpdate; Loading Loading @@ -217,7 +215,15 @@ public: bool needNewBuffer(int buffer) const; bool needNewBuffer(int buffer) const; status_t setDirtyRegion(int buffer, const Region& reg); status_t setDirtyRegion(int buffer, const Region& reg); status_t setCrop(int buffer, const Rect& reg); status_t setCrop(int buffer, const Rect& reg); status_t setBufferCount(int bufferCount); class SetBufferCountCallback { friend class SharedBufferClient; virtual status_t operator()(int bufferCount) const = 0; protected: virtual ~SetBufferCountCallback() { } }; status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc); private: private: friend struct Condition; friend struct Condition; Loading Loading @@ -249,11 +255,16 @@ private: inline const char* name() const { return "LockCondition"; } inline const char* name() const { return "LockCondition"; } }; }; int32_t computeTail() const; mutable RWLock mLock; int mNumBuffers; int32_t tail; int32_t tail; int32_t undoDequeueTail; int32_t undoDequeueTail; int32_t queued_head; int32_t queued_head; // statistics... // statistics... nsecs_t mDequeueTime[NUM_BUFFER_MAX]; nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX]; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -287,7 +298,8 @@ private: size_t mCapacity; size_t mCapacity; uint32_t mList; uint32_t mList; public: public: BufferList(size_t c = NUM_BUFFER_MAX) : mCapacity(c), mList(0) { } BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX) : mCapacity(c), mList(0) { } status_t add(int value); status_t add(int value); status_t remove(int value); status_t remove(int value); Loading Loading @@ -324,6 +336,9 @@ private: } } }; }; // this protects mNumBuffers and mBufferList mutable RWLock mLock; int mNumBuffers; BufferList mBufferList; BufferList mBufferList; struct UnlockUpdate : public UpdateBase { struct UnlockUpdate : public UpdateBase { Loading Loading @@ -373,7 +388,7 @@ struct surface_flinger_cblk_t // 4KB max uint8_t connected; uint8_t connected; uint8_t reserved[3]; uint8_t reserved[3]; uint32_t pad[7]; uint32_t pad[7]; display_cblk_t displays[NUM_DISPLAY_MAX]; display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX]; }; }; // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Loading libs/surfaceflinger/Barrier.h +0 −4 Original line number Original line Diff line number Diff line Loading @@ -29,10 +29,6 @@ public: inline Barrier() : state(CLOSED) { } inline Barrier() : state(CLOSED) { } inline ~Barrier() { } inline ~Barrier() { } void open() { void open() { // gcc memory barrier, this makes sure all memory writes // have been issued by gcc. On an SMP system we'd need a real // h/w barrier. asm volatile ("":::"memory"); Mutex::Autolock _l(lock); Mutex::Autolock _l(lock); state = OPENED; state = OPENED; cv.broadcast(); cv.broadcast(); Loading libs/surfaceflinger/Layer.cpp +84 −53 Original line number Original line Diff line number Diff line Loading @@ -60,7 +60,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, // no OpenGL operation is possible here, since we might not be // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. // in the OpenGL thread. lcblk = new SharedBufferServer( lcblk = new SharedBufferServer( client->ctrlblk, i, mBufferManager.getBufferCount(), client->ctrlblk, i, mBufferManager.getDefaultBufferCount(), getIdentity()); getIdentity()); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); Loading @@ -68,7 +68,10 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Layer::~Layer() Layer::~Layer() { { destroy(); // FIXME: must be called from the main UI thread EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); // the actual buffers will be destroyed here // the actual buffers will be destroyed here delete lcblk; delete lcblk; } } Loading @@ -81,17 +84,6 @@ void Layer::onRemoved() lcblk->setStatus(NO_INIT); lcblk->setStatus(NO_INIT); } } void Layer::destroy() { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; } sp<LayerBaseClient::Surface> Layer::createSurface() const sp<LayerBaseClient::Surface> Layer::createSurface() const { { return mSurface; return mSurface; Loading @@ -99,9 +91,17 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const status_t Layer::ditch() status_t Layer::ditch() { { // NOTE: Called from the main UI thread // the layer is not on screen anymore. free as much resources as possible // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); mFreezeLock.clear(); destroy(); EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -211,7 +211,7 @@ void Layer::onDraw(const Region& clip) const status_t Layer::setBufferCount(int bufferCount) status_t Layer::setBufferCount(int bufferCount) { { // this ensures our client doesn't go away while we're accessing // Ensures our client doesn't go away while we're accessing // the shared area. // the shared area. sp<Client> ourClient(client.promote()); sp<Client> ourClient(client.promote()); if (ourClient == 0) { if (ourClient == 0) { Loading @@ -219,15 +219,10 @@ status_t Layer::setBufferCount(int bufferCount) return DEAD_OBJECT; return DEAD_OBJECT; } } status_t err; // NOTE: lcblk->resize() is protected by an internal lock status_t err = lcblk->resize(bufferCount); // FIXME: resize() below is NOT thread-safe, we need to synchronize if (err == NO_ERROR) // the users of lcblk in our process (ie: retire), and we assume the mBufferManager.resize(bufferCount); // client is not mucking with the SharedStack, which is only enforced // by construction, therefore we need to protect ourselves against // buggy and malicious client (as always) err = lcblk->resize(bufferCount); return err; return err; } } Loading Loading @@ -544,12 +539,20 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Layer::BufferManager::BufferManager(TextureManager& tm) Layer::BufferManager::BufferManager(TextureManager& tm) : mTextureManager(tm), mActiveBuffer(0), mFailover(false) : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), mActiveBuffer(0), mFailover(false) { { } } size_t Layer::BufferManager::getBufferCount() const { Layer::BufferManager::~BufferManager() return NUM_BUFFERS; { } status_t Layer::BufferManager::resize(size_t size) { Mutex::Autolock _l(mLock); mNumBuffers = size; return NO_ERROR; } } // only for debugging // only for debugging Loading @@ -568,51 +571,55 @@ size_t Layer::BufferManager::getActiveBufferIndex() const { } } Texture Layer::BufferManager::getActiveTexture() const { Texture Layer::BufferManager::getActiveTexture() const { return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture; Texture res; if (mFailover) { res = mFailoverTexture; } else { static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture; } return res; } } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { const size_t activeBuffer = mActiveBuffer; BufferData const * const buffers = mBufferData; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); return mBufferData[mActiveBuffer].buffer; return buffers[activeBuffer].buffer; } } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { { BufferData* const buffers = mBufferData; sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); buffer = mBufferData[index].buffer; buffer = buffers[index].buffer; mBufferData[index].buffer = 0; buffers[index].buffer = 0; return buffer; return buffer; } } status_t Layer::BufferManager::attachBuffer(size_t index, status_t Layer::BufferManager::attachBuffer(size_t index, const sp<GraphicBuffer>& buffer) const sp<GraphicBuffer>& buffer) { { BufferData* const buffers = mBufferData; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); mBufferData[index].buffer = buffer; buffers[index].buffer = buffer; mBufferData[index].texture.dirty = true; buffers[index].texture.dirty = true; return NO_ERROR; } status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; return NO_ERROR; } } status_t Layer::BufferManager::destroy(EGLDisplay dpy) status_t Layer::BufferManager::destroy(EGLDisplay dpy) { { BufferData* const buffers = mBufferData; size_t num; { // scope for the lock Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); for (size_t i=0 ; i<NUM_BUFFERS ; i++) { num = mNumBuffers; destroyTexture(&mBufferData[i].texture, dpy); for (size_t i=0 ; i<num ; i++) { mBufferData[i].buffer = 0; buffers[i].buffer = 0; } } for (size_t i=0 ; i<num ; i++) { destroyTexture(&buffers[i].texture, dpy); } } destroyTexture(&mFailoverTexture, dpy); destroyTexture(&mFailoverTexture, dpy); return NO_ERROR; return NO_ERROR; Loading @@ -622,7 +629,7 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) const sp<GraphicBuffer>& buffer) { { size_t index = mActiveBuffer; size_t index = mActiveBuffer; Texture& texture(mBufferData[index].texture); Image& texture(mBufferData[index].texture); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); // if EGLImage fails, we switch to regular texture mode, and we // if EGLImage fails, we switch to regular texture mode, and we // free all resources associated with using EGLImages. // free all resources associated with using EGLImages. Loading @@ -631,7 +638,8 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, destroyTexture(&mFailoverTexture, dpy); destroyTexture(&mFailoverTexture, dpy); } else { } else { mFailover = true; mFailover = true; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { const size_t num = mNumBuffers; for (size_t i=0 ; i<num ; i++) { destroyTexture(&mBufferData[i].texture, dpy); destroyTexture(&mBufferData[i].texture, dpy); } } } } Loading @@ -644,6 +652,19 @@ status_t Layer::BufferManager::loadTexture( return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); } } status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, Loading @@ -661,6 +682,11 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); sp<Layer> owner(getOwner()); if (owner != 0) { if (owner != 0) { /* * requestBuffer() cannot be called from the main thread * as it could cause a dead-lock, since it may have to wait * on conditions updated my the main thread. */ buffer = owner->requestBuffer(index, usage); buffer = owner->requestBuffer(index, usage); } } return buffer; return buffer; Loading @@ -671,6 +697,11 @@ status_t Layer::SurfaceLayer::setBufferCount(int bufferCount) status_t err = DEAD_OBJECT; status_t err = DEAD_OBJECT; sp<Layer> owner(getOwner()); sp<Layer> owner(getOwner()); if (owner != 0) { if (owner != 0) { /* * setBufferCount() cannot be called from the main thread * as it could cause a dead-lock, since it may have to wait * on conditions updated my the main thread. */ err = owner->setBufferCount(bufferCount); err = owner->setBufferCount(bufferCount); } } return err; return err; Loading libs/surfaceflinger/Layer.h +14 −6 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,6 @@ private: sp<GraphicBuffer> requestBuffer(int index, int usage); sp<GraphicBuffer> requestBuffer(int index, int usage); status_t setBufferCount(int bufferCount); status_t setBufferCount(int bufferCount); void destroy(); class SurfaceLayer : public LayerBaseClient::Surface { class SurfaceLayer : public LayerBaseClient::Surface { public: public: Loading Loading @@ -120,25 +119,32 @@ private: static const size_t NUM_BUFFERS = 2; static const size_t NUM_BUFFERS = 2; struct BufferData { struct BufferData { sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; Texture texture; 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; mutable Mutex mLock; BufferData mBufferData[NUM_BUFFERS]; BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX]; size_t mNumBuffers; Texture mFailoverTexture; Texture mFailoverTexture; TextureManager& mTextureManager; TextureManager& mTextureManager; ssize_t mActiveBuffer; ssize_t mActiveBuffer; bool mFailover; bool mFailover; static status_t destroyTexture(Texture* tex, EGLDisplay dpy); static status_t destroyTexture(Image* tex, EGLDisplay dpy); public: public: static size_t getDefaultBufferCount() { return NUM_BUFFERS; } BufferManager(TextureManager& tm); BufferManager(TextureManager& tm); ~BufferManager(); size_t getBufferCount() const; // detach/attach buffer from/to given index // detach/attach buffer from/to given index sp<GraphicBuffer> detachBuffer(size_t index); sp<GraphicBuffer> detachBuffer(size_t index); status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); 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 // must be called from GL thread Loading Loading @@ -170,6 +176,8 @@ private: TextureManager mTextureManager; TextureManager mTextureManager; BufferManager mBufferManager; BufferManager mBufferManager; // this lock protects mWidth and mHeight which are accessed from // the main thread and requestBuffer's binder transaction thread. mutable Mutex mLock; mutable Mutex mLock; uint32_t mWidth; uint32_t mWidth; uint32_t mHeight; uint32_t mHeight; Loading libs/surfaceflinger/LayerBlur.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -95,7 +95,9 @@ void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirty mCacheDirty = false; mCacheDirty = false; } else { } else { if (!mAutoRefreshPending) { if (!mAutoRefreshPending) { mFlinger->signalDelayedEvent(ms2ns(500)); mFlinger->postMessageAsync( new MessageBase(MessageQueue::INVALIDATE), ms2ns(500)); mAutoRefreshPending = true; mAutoRefreshPending = true; } } } } Loading Loading
include/private/surfaceflinger/SharedBufferStack.h +29 −14 Original line number Original line Diff line number Diff line Loading @@ -55,12 +55,6 @@ namespace android { * * */ */ // When changing these values, the COMPILE_TIME_ASSERT at the end of this // file need to be updated. const unsigned int NUM_LAYERS_MAX = 31; const unsigned int NUM_BUFFER_MAX = 16; const unsigned int NUM_DISPLAY_MAX = 4; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- class Region; class Region; Loading @@ -82,6 +76,12 @@ class SharedBufferStack friend class SharedBufferServer; friend class SharedBufferServer; public: public: // When changing these values, the COMPILE_TIME_ASSERT at the end of this // file need to be updated. static const unsigned int NUM_LAYERS_MAX = 31; static const unsigned int NUM_BUFFER_MAX = 16; static const unsigned int NUM_DISPLAY_MAX = 4; struct Statistics { // 4 longs struct Statistics { // 4 longs typedef int32_t usecs_t; typedef int32_t usecs_t; usecs_t totalTime; usecs_t totalTime; Loading Loading @@ -147,7 +147,7 @@ private: // FIXME: this should be replaced by a lock-less primitive // FIXME: this should be replaced by a lock-less primitive Mutex lock; Mutex lock; Condition cv; Condition cv; SharedBufferStack surfaces[ NUM_LAYERS_MAX ]; SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ]; }; }; // ============================================================================ // ============================================================================ Loading @@ -155,7 +155,7 @@ private: class SharedBufferBase class SharedBufferBase { { public: public: SharedBufferBase(SharedClient* sharedClient, int surface, int num, SharedBufferBase(SharedClient* sharedClient, int surface, int32_t identity); int32_t identity); ~SharedBufferBase(); ~SharedBufferBase(); uint32_t getIdentity(); uint32_t getIdentity(); Loading @@ -166,9 +166,7 @@ public: protected: protected: SharedClient* const mSharedClient; SharedClient* const mSharedClient; SharedBufferStack* const mSharedStack; SharedBufferStack* const mSharedStack; int mNumBuffers; const int mIdentity; const int mIdentity; int32_t computeTail() const; friend struct Update; friend struct Update; friend struct QueueUpdate; friend struct QueueUpdate; Loading Loading @@ -217,7 +215,15 @@ public: bool needNewBuffer(int buffer) const; bool needNewBuffer(int buffer) const; status_t setDirtyRegion(int buffer, const Region& reg); status_t setDirtyRegion(int buffer, const Region& reg); status_t setCrop(int buffer, const Rect& reg); status_t setCrop(int buffer, const Rect& reg); status_t setBufferCount(int bufferCount); class SetBufferCountCallback { friend class SharedBufferClient; virtual status_t operator()(int bufferCount) const = 0; protected: virtual ~SetBufferCountCallback() { } }; status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc); private: private: friend struct Condition; friend struct Condition; Loading Loading @@ -249,11 +255,16 @@ private: inline const char* name() const { return "LockCondition"; } inline const char* name() const { return "LockCondition"; } }; }; int32_t computeTail() const; mutable RWLock mLock; int mNumBuffers; int32_t tail; int32_t tail; int32_t undoDequeueTail; int32_t undoDequeueTail; int32_t queued_head; int32_t queued_head; // statistics... // statistics... nsecs_t mDequeueTime[NUM_BUFFER_MAX]; nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX]; }; }; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -287,7 +298,8 @@ private: size_t mCapacity; size_t mCapacity; uint32_t mList; uint32_t mList; public: public: BufferList(size_t c = NUM_BUFFER_MAX) : mCapacity(c), mList(0) { } BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX) : mCapacity(c), mList(0) { } status_t add(int value); status_t add(int value); status_t remove(int value); status_t remove(int value); Loading Loading @@ -324,6 +336,9 @@ private: } } }; }; // this protects mNumBuffers and mBufferList mutable RWLock mLock; int mNumBuffers; BufferList mBufferList; BufferList mBufferList; struct UnlockUpdate : public UpdateBase { struct UnlockUpdate : public UpdateBase { Loading Loading @@ -373,7 +388,7 @@ struct surface_flinger_cblk_t // 4KB max uint8_t connected; uint8_t connected; uint8_t reserved[3]; uint8_t reserved[3]; uint32_t pad[7]; uint32_t pad[7]; display_cblk_t displays[NUM_DISPLAY_MAX]; display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX]; }; }; // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Loading
libs/surfaceflinger/Barrier.h +0 −4 Original line number Original line Diff line number Diff line Loading @@ -29,10 +29,6 @@ public: inline Barrier() : state(CLOSED) { } inline Barrier() : state(CLOSED) { } inline ~Barrier() { } inline ~Barrier() { } void open() { void open() { // gcc memory barrier, this makes sure all memory writes // have been issued by gcc. On an SMP system we'd need a real // h/w barrier. asm volatile ("":::"memory"); Mutex::Autolock _l(lock); Mutex::Autolock _l(lock); state = OPENED; state = OPENED; cv.broadcast(); cv.broadcast(); Loading
libs/surfaceflinger/Layer.cpp +84 −53 Original line number Original line Diff line number Diff line Loading @@ -60,7 +60,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, // no OpenGL operation is possible here, since we might not be // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. // in the OpenGL thread. lcblk = new SharedBufferServer( lcblk = new SharedBufferServer( client->ctrlblk, i, mBufferManager.getBufferCount(), client->ctrlblk, i, mBufferManager.getDefaultBufferCount(), getIdentity()); getIdentity()); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() ); Loading @@ -68,7 +68,10 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Layer::~Layer() Layer::~Layer() { { destroy(); // FIXME: must be called from the main UI thread EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); // the actual buffers will be destroyed here // the actual buffers will be destroyed here delete lcblk; delete lcblk; } } Loading @@ -81,17 +84,6 @@ void Layer::onRemoved() lcblk->setStatus(NO_INIT); lcblk->setStatus(NO_INIT); } } void Layer::destroy() { EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; } sp<LayerBaseClient::Surface> Layer::createSurface() const sp<LayerBaseClient::Surface> Layer::createSurface() const { { return mSurface; return mSurface; Loading @@ -99,9 +91,17 @@ sp<LayerBaseClient::Surface> Layer::createSurface() const status_t Layer::ditch() status_t Layer::ditch() { { // NOTE: Called from the main UI thread // the layer is not on screen anymore. free as much resources as possible // the layer is not on screen anymore. free as much resources as possible mFreezeLock.clear(); mFreezeLock.clear(); destroy(); EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); mBufferManager.destroy(dpy); mSurface.clear(); Mutex::Autolock _l(mLock); mWidth = mHeight = 0; return NO_ERROR; return NO_ERROR; } } Loading Loading @@ -211,7 +211,7 @@ void Layer::onDraw(const Region& clip) const status_t Layer::setBufferCount(int bufferCount) status_t Layer::setBufferCount(int bufferCount) { { // this ensures our client doesn't go away while we're accessing // Ensures our client doesn't go away while we're accessing // the shared area. // the shared area. sp<Client> ourClient(client.promote()); sp<Client> ourClient(client.promote()); if (ourClient == 0) { if (ourClient == 0) { Loading @@ -219,15 +219,10 @@ status_t Layer::setBufferCount(int bufferCount) return DEAD_OBJECT; return DEAD_OBJECT; } } status_t err; // NOTE: lcblk->resize() is protected by an internal lock status_t err = lcblk->resize(bufferCount); // FIXME: resize() below is NOT thread-safe, we need to synchronize if (err == NO_ERROR) // the users of lcblk in our process (ie: retire), and we assume the mBufferManager.resize(bufferCount); // client is not mucking with the SharedStack, which is only enforced // by construction, therefore we need to protect ourselves against // buggy and malicious client (as always) err = lcblk->resize(bufferCount); return err; return err; } } Loading Loading @@ -544,12 +539,20 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Layer::BufferManager::BufferManager(TextureManager& tm) Layer::BufferManager::BufferManager(TextureManager& tm) : mTextureManager(tm), mActiveBuffer(0), mFailover(false) : mNumBuffers(NUM_BUFFERS), mTextureManager(tm), mActiveBuffer(0), mFailover(false) { { } } size_t Layer::BufferManager::getBufferCount() const { Layer::BufferManager::~BufferManager() return NUM_BUFFERS; { } status_t Layer::BufferManager::resize(size_t size) { Mutex::Autolock _l(mLock); mNumBuffers = size; return NO_ERROR; } } // only for debugging // only for debugging Loading @@ -568,51 +571,55 @@ size_t Layer::BufferManager::getActiveBufferIndex() const { } } Texture Layer::BufferManager::getActiveTexture() const { Texture Layer::BufferManager::getActiveTexture() const { return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture; Texture res; if (mFailover) { res = mFailoverTexture; } else { static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture; } return res; } } sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const { const size_t activeBuffer = mActiveBuffer; BufferData const * const buffers = mBufferData; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); return mBufferData[mActiveBuffer].buffer; return buffers[activeBuffer].buffer; } } sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index) { { BufferData* const buffers = mBufferData; sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); buffer = mBufferData[index].buffer; buffer = buffers[index].buffer; mBufferData[index].buffer = 0; buffers[index].buffer = 0; return buffer; return buffer; } } status_t Layer::BufferManager::attachBuffer(size_t index, status_t Layer::BufferManager::attachBuffer(size_t index, const sp<GraphicBuffer>& buffer) const sp<GraphicBuffer>& buffer) { { BufferData* const buffers = mBufferData; Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); mBufferData[index].buffer = buffer; buffers[index].buffer = buffer; mBufferData[index].texture.dirty = true; buffers[index].texture.dirty = true; return NO_ERROR; } status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; return NO_ERROR; } } status_t Layer::BufferManager::destroy(EGLDisplay dpy) status_t Layer::BufferManager::destroy(EGLDisplay dpy) { { BufferData* const buffers = mBufferData; size_t num; { // scope for the lock Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock); for (size_t i=0 ; i<NUM_BUFFERS ; i++) { num = mNumBuffers; destroyTexture(&mBufferData[i].texture, dpy); for (size_t i=0 ; i<num ; i++) { mBufferData[i].buffer = 0; buffers[i].buffer = 0; } } for (size_t i=0 ; i<num ; i++) { destroyTexture(&buffers[i].texture, dpy); } } destroyTexture(&mFailoverTexture, dpy); destroyTexture(&mFailoverTexture, dpy); return NO_ERROR; return NO_ERROR; Loading @@ -622,7 +629,7 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, const sp<GraphicBuffer>& buffer) const sp<GraphicBuffer>& buffer) { { size_t index = mActiveBuffer; size_t index = mActiveBuffer; Texture& texture(mBufferData[index].texture); Image& texture(mBufferData[index].texture); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); status_t err = mTextureManager.initEglImage(&texture, dpy, buffer); // if EGLImage fails, we switch to regular texture mode, and we // if EGLImage fails, we switch to regular texture mode, and we // free all resources associated with using EGLImages. // free all resources associated with using EGLImages. Loading @@ -631,7 +638,8 @@ status_t Layer::BufferManager::initEglImage(EGLDisplay dpy, destroyTexture(&mFailoverTexture, dpy); destroyTexture(&mFailoverTexture, dpy); } else { } else { mFailover = true; mFailover = true; for (size_t i=0 ; i<NUM_BUFFERS ; i++) { const size_t num = mNumBuffers; for (size_t i=0 ; i<num ; i++) { destroyTexture(&mBufferData[i].texture, dpy); destroyTexture(&mBufferData[i].texture, dpy); } } } } Loading @@ -644,6 +652,19 @@ status_t Layer::BufferManager::loadTexture( return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); return mTextureManager.loadTexture(&mFailoverTexture, dirty, t); } } status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy) { if (tex->name != -1U) { glDeleteTextures(1, &tex->name); tex->name = -1U; } if (tex->image != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(dpy, tex->image); tex->image = EGL_NO_IMAGE_KHR; } return NO_ERROR; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, Loading @@ -661,6 +682,11 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage) sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; sp<Layer> owner(getOwner()); sp<Layer> owner(getOwner()); if (owner != 0) { if (owner != 0) { /* * requestBuffer() cannot be called from the main thread * as it could cause a dead-lock, since it may have to wait * on conditions updated my the main thread. */ buffer = owner->requestBuffer(index, usage); buffer = owner->requestBuffer(index, usage); } } return buffer; return buffer; Loading @@ -671,6 +697,11 @@ status_t Layer::SurfaceLayer::setBufferCount(int bufferCount) status_t err = DEAD_OBJECT; status_t err = DEAD_OBJECT; sp<Layer> owner(getOwner()); sp<Layer> owner(getOwner()); if (owner != 0) { if (owner != 0) { /* * setBufferCount() cannot be called from the main thread * as it could cause a dead-lock, since it may have to wait * on conditions updated my the main thread. */ err = owner->setBufferCount(bufferCount); err = owner->setBufferCount(bufferCount); } } return err; return err; Loading
libs/surfaceflinger/Layer.h +14 −6 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,6 @@ private: sp<GraphicBuffer> requestBuffer(int index, int usage); sp<GraphicBuffer> requestBuffer(int index, int usage); status_t setBufferCount(int bufferCount); status_t setBufferCount(int bufferCount); void destroy(); class SurfaceLayer : public LayerBaseClient::Surface { class SurfaceLayer : public LayerBaseClient::Surface { public: public: Loading Loading @@ -120,25 +119,32 @@ private: static const size_t NUM_BUFFERS = 2; static const size_t NUM_BUFFERS = 2; struct BufferData { struct BufferData { sp<GraphicBuffer> buffer; sp<GraphicBuffer> buffer; Texture texture; 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; mutable Mutex mLock; BufferData mBufferData[NUM_BUFFERS]; BufferData mBufferData[SharedBufferStack::NUM_BUFFER_MAX]; size_t mNumBuffers; Texture mFailoverTexture; Texture mFailoverTexture; TextureManager& mTextureManager; TextureManager& mTextureManager; ssize_t mActiveBuffer; ssize_t mActiveBuffer; bool mFailover; bool mFailover; static status_t destroyTexture(Texture* tex, EGLDisplay dpy); static status_t destroyTexture(Image* tex, EGLDisplay dpy); public: public: static size_t getDefaultBufferCount() { return NUM_BUFFERS; } BufferManager(TextureManager& tm); BufferManager(TextureManager& tm); ~BufferManager(); size_t getBufferCount() const; // detach/attach buffer from/to given index // detach/attach buffer from/to given index sp<GraphicBuffer> detachBuffer(size_t index); sp<GraphicBuffer> detachBuffer(size_t index); status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer); 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 // must be called from GL thread Loading Loading @@ -170,6 +176,8 @@ private: TextureManager mTextureManager; TextureManager mTextureManager; BufferManager mBufferManager; BufferManager mBufferManager; // this lock protects mWidth and mHeight which are accessed from // the main thread and requestBuffer's binder transaction thread. mutable Mutex mLock; mutable Mutex mLock; uint32_t mWidth; uint32_t mWidth; uint32_t mHeight; uint32_t mHeight; Loading
libs/surfaceflinger/LayerBlur.cpp +3 −1 Original line number Original line Diff line number Diff line Loading @@ -95,7 +95,9 @@ void LayerBlur::unlockPageFlip(const Transform& planeTransform, Region& outDirty mCacheDirty = false; mCacheDirty = false; } else { } else { if (!mAutoRefreshPending) { if (!mAutoRefreshPending) { mFlinger->signalDelayedEvent(ms2ns(500)); mFlinger->postMessageAsync( new MessageBase(MessageQueue::INVALIDATE), ms2ns(500)); mAutoRefreshPending = true; mAutoRefreshPending = true; } } } } Loading