From 698c0873cf2e07bdc7fd1e72169aee2a19fa40d7 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 28 Jun 2011 19:09:31 -0700 Subject: [PATCH] SF transactions are now O(1) wrt IPC instead of O(N). Change-Id: I57669852cbf6aabae244ea86940a08a5a27ffc43 --- include/private/surfaceflinger/LayerState.h | 8 + include/surfaceflinger/ISurfaceComposer.h | 7 +- .../surfaceflinger/ISurfaceComposerClient.h | 7 - .../surfaceflinger/SurfaceComposerClient.h | 26 +- include/utils/SortedVector.h | 2 + include/utils/Vector.h | 26 +- libs/gui/ISurfaceComposer.cpp | 35 +- libs/gui/ISurfaceComposerClient.cpp | 25 +- libs/gui/LayerState.cpp | 11 + libs/gui/SurfaceComposerClient.cpp | 639 +++++++++--------- libs/gui/tests/SurfaceTexture_test.cpp | 4 +- libs/gui/tests/Surface_test.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 152 ++--- services/surfaceflinger/SurfaceFlinger.h | 9 +- .../surfaceflinger/tests/resize/resize.cpp | 8 +- .../surfaceflinger/tests/surface/surface.cpp | 4 +- 16 files changed, 464 insertions(+), 503 deletions(-) diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h index d7fe572e9..d2fed418f 100644 --- a/include/private/surfaceflinger/LayerState.h +++ b/include/private/surfaceflinger/LayerState.h @@ -29,6 +29,7 @@ namespace android { class Parcel; +class ISurfaceComposerClient; struct layer_state_t { @@ -68,6 +69,13 @@ struct layer_state_t { Region transparentRegion; }; +struct ComposerState { + sp client; + layer_state_t state; + status_t write(Parcel& output) const; + status_t read(const Parcel& input); +}; + }; // namespace android #endif // ANDROID_SF_LAYER_STATE_H diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 03fd01b31..dba98a32c 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -34,6 +34,7 @@ namespace android { // ---------------------------------------------------------------------------- class IMemoryHeap; +class ComposerState; class ISurfaceComposer : public IInterface { @@ -105,8 +106,7 @@ public: virtual sp getCblk() const = 0; /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ - virtual void openGlobalTransaction() = 0; - virtual void closeGlobalTransaction() = 0; + virtual void setTransactionState(const Vector& state) = 0; /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0; @@ -149,8 +149,7 @@ public: CREATE_CONNECTION, CREATE_GRAPHIC_BUFFER_ALLOC, GET_CBLK, - OPEN_GLOBAL_TRANSACTION, - CLOSE_GLOBAL_TRANSACTION, + SET_TRANSACTION_STATE, SET_ORIENTATION, FREEZE_DISPLAY, UNFREEZE_DISPLAY, diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h index 2e75a0e4c..6e9a65464 100644 --- a/include/surfaceflinger/ISurfaceComposerClient.h +++ b/include/surfaceflinger/ISurfaceComposerClient.h @@ -37,8 +37,6 @@ typedef int32_t DisplayID; // ---------------------------------------------------------------------------- -class layer_state_t; - class ISurfaceComposerClient : public IInterface { public: @@ -69,11 +67,6 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t destroySurface(SurfaceID sid) = 0; - - /* - * Requires ACCESS_SURFACE_FLINGER permission - */ - virtual status_t setState(int32_t count, const layer_state_t* states) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 140b9f860..7fbbfb24f 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -37,10 +37,12 @@ namespace android { // --------------------------------------------------------------------------- class DisplayInfo; +class Composer; class IMemoryHeap; class ISurfaceComposer; class Region; class surface_flinger_cblk_t; +struct layer_state_t; // --------------------------------------------------------------------------- @@ -59,8 +61,11 @@ public: // --------------------------------------------------------------------------- +class Composer; + class SurfaceComposerClient : public RefBase { + friend class Composer; public: SurfaceComposerClient(); virtual ~SurfaceComposerClient(); @@ -101,13 +106,7 @@ public: // All composer parameters must be changed within a transaction // several surfaces can be updated in one transaction, all changes are // committed at once when the transaction is closed. - // CloseTransaction() usually requires an IPC with the server. - - //! Open a composer transaction - status_t openTransaction(); - - //! commit the transaction - status_t closeTransaction(); + // closeGlobalTransaction() usually requires an IPC with the server. //! Open a composer transaction on all active SurfaceComposerClients. static void openGlobalTransaction(); @@ -152,19 +151,12 @@ public: private: virtual void onFirstRef(); - inline layer_state_t* get_state_l(SurfaceID id); - layer_state_t* lockLayerState(SurfaceID id); - inline void unlockLayerState(); + Composer& getComposer(); - mutable Mutex mLock; - SortedVector mStates; - int32_t mTransactionOpen; - layer_state_t* mPrebuiltLayerState; - - // these don't need to be protected because they never change - // after assignment + mutable Mutex mLock; status_t mStatus; sp mClient; + Composer& mComposer; }; // --------------------------------------------------------------------------- diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h index 8beec5732..0e98aeb05 100644 --- a/include/utils/SortedVector.h +++ b/include/utils/SortedVector.h @@ -32,6 +32,8 @@ namespace android { template class SortedVector : private SortedVectorImpl { + friend class Vector; + public: typedef TYPE value_type; diff --git a/include/utils/Vector.h b/include/utils/Vector.h index f1e87e609..b908e2ab2 100644 --- a/include/utils/Vector.h +++ b/include/utils/Vector.h @@ -29,6 +29,9 @@ namespace android { +template +class SortedVector; + /*! * The main templated vector class ensuring type safety * while making use of VectorImpl. @@ -47,13 +50,17 @@ public: Vector(); Vector(const Vector& rhs); + explicit Vector(const SortedVector& rhs); virtual ~Vector(); /*! copy operator */ const Vector& operator = (const Vector& rhs) const; Vector& operator = (const Vector& rhs); - /* + const Vector& operator = (const SortedVector& rhs) const; + Vector& operator = (const SortedVector& rhs); + + /* * empty the vector */ @@ -214,6 +221,11 @@ Vector::Vector(const Vector& rhs) : VectorImpl(rhs) { } +template inline +Vector::Vector(const SortedVector& rhs) + : VectorImpl(static_cast(rhs)) { +} + template inline Vector::~Vector() { finish_vector(); @@ -227,6 +239,18 @@ Vector& Vector::operator = (const Vector& rhs) { template inline const Vector& Vector::operator = (const Vector& rhs) const { + VectorImpl::operator = (static_cast(rhs)); + return *this; +} + +template inline +Vector& Vector::operator = (const SortedVector& rhs) { + VectorImpl::operator = (static_cast(rhs)); + return *this; +} + +template inline +const Vector& Vector::operator = (const SortedVector& rhs) const { VectorImpl::operator = (rhs); return *this; } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 40450a3d0..c1156d5c8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include #include @@ -74,18 +76,17 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual void openGlobalTransaction() + virtual void setTransactionState(const Vector& state) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply); - } - - virtual void closeGlobalTransaction() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply); + Vector::const_iterator b(state.begin()); + Vector::const_iterator e(state.end()); + data.writeInt32(state.size()); + for ( ; b != e ; ++b ) { + b->write(data); + } + remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) @@ -218,13 +219,17 @@ status_t BnSurfaceComposer::onTransact( sp b = createGraphicBufferAlloc()->asBinder(); reply->writeStrongBinder(b); } break; - case OPEN_GLOBAL_TRANSACTION: { + case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - openGlobalTransaction(); - } break; - case CLOSE_GLOBAL_TRANSACTION: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - closeGlobalTransaction(); + size_t count = data.readInt32(); + ComposerState s; + Vector state; + state.setCapacity(count); + for (size_t i=0 ; i @@ -92,17 +91,6 @@ public: remote()->transact(DESTROY_SURFACE, data, &reply); return reply.readInt32(); } - - virtual status_t setState(int32_t count, const layer_state_t* states) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); - data.writeInt32(count); - for (int i=0 ; itransact(SET_STATE, data, &reply); - return reply.readInt32(); - } }; IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient"); @@ -133,17 +121,6 @@ status_t BnSurfaceComposerClient::onTransact( reply->writeInt32( destroySurface( data.readInt32() ) ); return NO_ERROR; } break; - case SET_STATE: { - CHECK_INTERFACE(ISurfaceComposerClient, data, reply); - int32_t count = data.readInt32(); - layer_state_t* states = new layer_state_t[count]; - for (int i=0 ; iwriteInt32(err); - return NO_ERROR; - } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 01c4c7ebf..87901e87f 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace android { @@ -58,4 +59,14 @@ status_t layer_state_t::read(const Parcel& input) return NO_ERROR; } +status_t ComposerState::write(Parcel& output) const { + output.writeStrongBinder(client->asBinder()); + return state.write(output); +} + +status_t ComposerState::read(const Parcel& input) { + client = interface_cast(input.readStrongBinder()); + return state.read(input); +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1678711aa..8cead808a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -74,75 +74,52 @@ static inline surface_flinger_cblk_t const volatile * get_cblk() { // --------------------------------------------------------------------------- +// NOTE: this is NOT a member function (it's a friend defined with its +// declaration). +static inline +int compare_type( const ComposerState& lhs, const ComposerState& rhs) { + if (lhs.client < rhs.client) return -1; + if (lhs.client > rhs.client) return 1; + if (lhs.state.surface < rhs.state.surface) return -1; + if (lhs.state.surface > rhs.state.surface) return 1; + return 0; +} + class Composer : public Singleton { - Mutex mLock; - SortedVector< wp > mActiveConnections; - SortedVector > mOpenTransactions; - - Composer() : Singleton() { - } - - void addClientImpl(const sp& client) { - Mutex::Autolock _l(mLock); - mActiveConnections.add(client); - } - - void removeClientImpl(const sp& client) { - Mutex::Autolock _l(mLock); - mActiveConnections.remove(client); - } - - void openGlobalTransactionImpl() - { - Mutex::Autolock _l(mLock); - if (mOpenTransactions.size()) { - LOGE("openGlobalTransaction() called more than once. skipping."); - return; - } - const size_t N = mActiveConnections.size(); - for (size_t i=0; i client(mActiveConnections[i].promote()); - if (client != 0 && mOpenTransactions.indexOf(client) < 0) { - if (client->openTransaction() == NO_ERROR) { - mOpenTransactions.add(client); - } else { - LOGE("openTransaction on client %p failed", client.get()); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } - } - } - - void closeGlobalTransactionImpl() - { - mLock.lock(); - SortedVector< sp > clients(mOpenTransactions); - mOpenTransactions.clear(); - mLock.unlock(); - - sp sm(getComposerService()); - sm->openGlobalTransaction(); - const size_t N = clients.size(); - for (size_t i=0; icloseTransaction(); - } - sm->closeGlobalTransaction(); - } - friend class Singleton; + mutable Mutex mLock; + SortedVector mStates; + + Composer() : Singleton() { } + + void closeGlobalTransactionImpl(); + + layer_state_t* getLayerStateLocked( + const sp& client, SurfaceID id); + public: - static void addClient(const sp& client) { - Composer::getInstance().addClientImpl(client); - } - static void removeClient(const sp& client) { - Composer::getInstance().removeClientImpl(client); - } - static void openGlobalTransaction() { - Composer::getInstance().openGlobalTransactionImpl(); - } + + status_t setPosition(const sp& client, SurfaceID id, + int32_t x, int32_t y); + status_t setSize(const sp& client, SurfaceID id, + uint32_t w, uint32_t h); + status_t setLayer(const sp& client, SurfaceID id, + int32_t z); + status_t setFlags(const sp& client, SurfaceID id, + uint32_t flags, uint32_t mask); + status_t setTransparentRegionHint( + const sp& client, SurfaceID id, + const Region& transparentRegion); + status_t setAlpha(const sp& client, SurfaceID id, + float alpha); + status_t setMatrix(const sp& client, SurfaceID id, + float dsdx, float dtdx, float dsdy, float dtdy); + status_t setFreezeTint( + const sp& client, SurfaceID id, + uint32_t tint); + static void closeGlobalTransaction() { Composer::getInstance().closeGlobalTransactionImpl(); } @@ -152,69 +129,306 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- -static inline int compare_type( const layer_state_t& lhs, - const layer_state_t& rhs) { - if (lhs.surface < rhs.surface) return -1; - if (lhs.surface > rhs.surface) return 1; - return 0; +void Composer::closeGlobalTransactionImpl() { + sp sm(getComposerService()); + + Vector transaction; + + { // scope for the lock + Mutex::Autolock _l(mLock); + transaction = mStates; + mStates.clear(); + } + + sm->setTransactionState(transaction); } +layer_state_t* Composer::getLayerStateLocked( + const sp& client, SurfaceID id) { + + ComposerState s; + s.client = client->mClient; + s.state.surface = id; + + ssize_t index = mStates.indexOf(s); + if (index < 0) { + // we don't have it, add an initialized layer_state to our list + index = mStates.add(s); + } + + ComposerState* const out = mStates.editArray(); + return &(out[index].state); +} + +status_t Composer::setPosition(const sp& client, + SurfaceID id, int32_t x, int32_t y) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::ePositionChanged; + s->x = x; + s->y = y; + return NO_ERROR; +} + +status_t Composer::setSize(const sp& client, + SurfaceID id, uint32_t w, uint32_t h) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eSizeChanged; + s->w = w; + s->h = h; + return NO_ERROR; +} + +status_t Composer::setLayer(const sp& client, + SurfaceID id, int32_t z) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eLayerChanged; + s->z = z; + return NO_ERROR; +} + +status_t Composer::setFlags(const sp& client, + SurfaceID id, uint32_t flags, + uint32_t mask) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eVisibilityChanged; + s->flags &= ~mask; + s->flags |= (flags & mask); + s->mask |= mask; + return NO_ERROR; +} + +status_t Composer::setTransparentRegionHint( + const sp& client, SurfaceID id, + const Region& transparentRegion) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eTransparentRegionChanged; + s->transparentRegion = transparentRegion; + return NO_ERROR; +} + +status_t Composer::setAlpha(const sp& client, + SurfaceID id, float alpha) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eAlphaChanged; + s->alpha = alpha; + return NO_ERROR; +} + +status_t Composer::setMatrix(const sp& client, + SurfaceID id, float dsdx, float dtdx, + float dsdy, float dtdy) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eMatrixChanged; + layer_state_t::matrix22_t matrix; + matrix.dsdx = dsdx; + matrix.dtdx = dtdx; + matrix.dsdy = dsdy; + matrix.dtdy = dtdy; + s->matrix = matrix; + return NO_ERROR; +} + +status_t Composer::setFreezeTint(const sp& client, + SurfaceID id, uint32_t tint) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) + return BAD_INDEX; + s->what |= ISurfaceComposer::eFreezeTintChanged; + s->tint = tint; + return NO_ERROR; +} + +// --------------------------------------------------------------------------- + SurfaceComposerClient::SurfaceComposerClient() - : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT) + : mStatus(NO_INIT), mComposer(Composer::getInstance()) { } -void SurfaceComposerClient::onFirstRef() -{ +void SurfaceComposerClient::onFirstRef() { sp sm(getComposerService()); if (sm != 0) { sp conn = sm->createConnection(); if (conn != 0) { mClient = conn; - Composer::addClient(this); - mPrebuiltLayerState = new layer_state_t; mStatus = NO_ERROR; } } } -SurfaceComposerClient::~SurfaceComposerClient() -{ - delete mPrebuiltLayerState; +SurfaceComposerClient::~SurfaceComposerClient() { dispose(); } -status_t SurfaceComposerClient::initCheck() const -{ +status_t SurfaceComposerClient::initCheck() const { return mStatus; } -sp SurfaceComposerClient::connection() const -{ +sp SurfaceComposerClient::connection() const { return (mClient != 0) ? mClient->asBinder() : 0; } status_t SurfaceComposerClient::linkToComposerDeath( const sp& recipient, - void* cookie, uint32_t flags) -{ + void* cookie, uint32_t flags) { sp sm(getComposerService()); return sm->asBinder()->linkToDeath(recipient, cookie, flags); } -void SurfaceComposerClient::dispose() -{ +void SurfaceComposerClient::dispose() { // this can be called more than once. sp client; Mutex::Autolock _lm(mLock); if (mClient != 0) { - Composer::removeClient(this); client = mClient; // hold ref while lock is held mClient.clear(); } mStatus = NO_INIT; } +sp SurfaceComposerClient::createSurface( + DisplayID display, + uint32_t w, + uint32_t h, + PixelFormat format, + uint32_t flags) +{ + String8 name; + const size_t SIZE = 128; + char buffer[SIZE]; + snprintf(buffer, SIZE, "", getpid()); + name.append(buffer); + + return SurfaceComposerClient::createSurface(name, display, + w, h, format, flags); +} + +sp SurfaceComposerClient::createSurface( + const String8& name, + DisplayID display, + uint32_t w, + uint32_t h, + PixelFormat format, + uint32_t flags) +{ + sp result; + if (mStatus == NO_ERROR) { + ISurfaceComposerClient::surface_data_t data; + sp surface = mClient->createSurface(&data, name, + display, w, h, format, flags); + if (surface != 0) { + result = new SurfaceControl(this, surface, data, w, h, format, flags); + } + } + return result; +} + +status_t SurfaceComposerClient::destroySurface(SurfaceID sid) { + if (mStatus != NO_ERROR) + return mStatus; + status_t err = mClient->destroySurface(sid); + return err; +} + +inline Composer& SurfaceComposerClient::getComposer() { + return mComposer; +} + +// ---------------------------------------------------------------------------- + +void SurfaceComposerClient::openGlobalTransaction() { + // Currently a no-op +} + +void SurfaceComposerClient::closeGlobalTransaction() { + Composer::closeGlobalTransaction(); +} + +// ---------------------------------------------------------------------------- + +status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { + return getComposer().setFreezeTint(this, id, tint); +} + +status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) { + return getComposer().setPosition(this, id, x, y); +} + +status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) { + return getComposer().setSize(this, id, w, h); +} + +status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { + return getComposer().setLayer(this, id, z); +} + +status_t SurfaceComposerClient::hide(SurfaceID id) { + return getComposer().setFlags(this, id, + ISurfaceComposer::eLayerHidden, + ISurfaceComposer::eLayerHidden); +} + +status_t SurfaceComposerClient::show(SurfaceID id, int32_t) { + return getComposer().setFlags(this, id, + 0, + ISurfaceComposer::eLayerHidden); +} + +status_t SurfaceComposerClient::freeze(SurfaceID id) { + return getComposer().setFlags(this, id, + ISurfaceComposer::eLayerFrozen, + ISurfaceComposer::eLayerFrozen); +} + +status_t SurfaceComposerClient::unfreeze(SurfaceID id) { + return getComposer().setFlags(this, id, + 0, + ISurfaceComposer::eLayerFrozen); +} + +status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, + uint32_t mask) { + return getComposer().setFlags(this, id, flags, mask); +} + +status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id, + const Region& transparentRegion) { + return getComposer().setTransparentRegionHint(this, id, transparentRegion); +} + +status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { + return getComposer().setAlpha(this, id, alpha); +} + +status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx, + float dsdy, float dtdy) { + return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy); +} + +// ---------------------------------------------------------------------------- + status_t SurfaceComposerClient::getDisplayInfo( DisplayID dpy, DisplayInfo* info) { @@ -273,70 +487,7 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays() return n; } -sp SurfaceComposerClient::createSurface( - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - String8 name; - const size_t SIZE = 128; - char buffer[SIZE]; - snprintf(buffer, SIZE, "", getpid()); - name.append(buffer); - - return SurfaceComposerClient::createSurface(name, display, - w, h, format, flags); -} - -sp SurfaceComposerClient::createSurface( - const String8& name, - DisplayID display, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags) -{ - sp result; - if (mStatus == NO_ERROR) { - ISurfaceComposerClient::surface_data_t data; - sp surface = mClient->createSurface(&data, name, - display, w, h, format, flags); - if (surface != 0) { - result = new SurfaceControl(this, surface, data, w, h, format, flags); - } - } - return result; -} - -status_t SurfaceComposerClient::destroySurface(SurfaceID sid) -{ - if (mStatus != NO_ERROR) - return mStatus; - - // it's okay to destroy a surface while a transaction is open, - // (transactions really are a client-side concept) - // however, this indicates probably a misuse of the API or a bug - // in the client code. - LOGW_IF(mTransactionOpen, - "Destroying surface while a transaction is open. " - "Client %p: destroying surface %d, mTransactionOpen=%d", - this, sid, mTransactionOpen); - - status_t err = mClient->destroySurface(sid); - return err; -} - -void SurfaceComposerClient::openGlobalTransaction() -{ - Composer::openGlobalTransaction(); -} - -void SurfaceComposerClient::closeGlobalTransaction() -{ - Composer::closeGlobalTransaction(); -} +// ---------------------------------------------------------------------------- status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) { @@ -350,199 +501,13 @@ status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags) return sm->unfreezeDisplay(dpy, flags); } -int SurfaceComposerClient::setOrientation(DisplayID dpy, +int SurfaceComposerClient::setOrientation(DisplayID dpy, int orientation, uint32_t flags) { sp sm(getComposerService()); return sm->setOrientation(dpy, orientation, flags); } -status_t SurfaceComposerClient::openTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - Mutex::Autolock _l(mLock); - mTransactionOpen++; - return NO_ERROR; -} - -status_t SurfaceComposerClient::closeTransaction() -{ - if (mStatus != NO_ERROR) - return mStatus; - - Mutex::Autolock _l(mLock); - if (mTransactionOpen <= 0) { - LOGE( "closeTransaction (client %p, mTransactionOpen=%d) " - "called more times than openTransaction()", - this, mTransactionOpen); - return INVALID_OPERATION; - } - - if (mTransactionOpen >= 2) { - mTransactionOpen--; - return NO_ERROR; - } - - mTransactionOpen = 0; - const ssize_t count = mStates.size(); - if (count) { - mClient->setState(count, mStates.array()); - mStates.clear(); - } - return NO_ERROR; -} - -layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index) -{ - // API usage error, do nothing. - if (mTransactionOpen<=0) { - LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d", - this, int(index), mTransactionOpen); - return 0; - } - - // use mPrebuiltLayerState just to find out if we already have it - layer_state_t& dummy(*mPrebuiltLayerState); - dummy.surface = index; - ssize_t i = mStates.indexOf(dummy); - if (i < 0) { - // we don't have it, add an initialized layer_state to our list - i = mStates.add(dummy); - } - return mStates.editArray() + i; -} - -layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id) -{ - layer_state_t* s; - mLock.lock(); - s = get_state_l(id); - if (!s) mLock.unlock(); - return s; -} - -void SurfaceComposerClient::unlockLayerState() -{ - mLock.unlock(); -} - -status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::ePositionChanged; - s->x = x; - s->y = y; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eSizeChanged; - s->w = w; - s->h = h; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eLayerChanged; - s->z = z; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::hide(SurfaceID id) -{ - return setFlags(id, ISurfaceComposer::eLayerHidden, - ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::show(SurfaceID id, int32_t) -{ - return setFlags(id, 0, ISurfaceComposer::eLayerHidden); -} - -status_t SurfaceComposerClient::freeze(SurfaceID id) -{ - return setFlags(id, ISurfaceComposer::eLayerFrozen, - ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::unfreeze(SurfaceID id) -{ - return setFlags(id, 0, ISurfaceComposer::eLayerFrozen); -} - -status_t SurfaceComposerClient::setFlags(SurfaceID id, - uint32_t flags, uint32_t mask) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eVisibilityChanged; - s->flags &= ~mask; - s->flags |= (flags & mask); - s->mask |= mask; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setTransparentRegionHint( - SurfaceID id, const Region& transparentRegion) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eTransparentRegionChanged; - s->transparentRegion = transparentRegion; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eAlphaChanged; - s->alpha = alpha; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setMatrix( - SurfaceID id, - float dsdx, float dtdx, - float dsdy, float dtdy ) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eMatrixChanged; - layer_state_t::matrix22_t matrix; - matrix.dsdx = dsdx; - matrix.dtdx = dtdx; - matrix.dsdy = dsdy; - matrix.dtdy = dtdy; - s->matrix = matrix; - unlockLayerState(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) -{ - layer_state_t* s = lockLayerState(id); - if (!s) return BAD_INDEX; - s->what |= ISurfaceComposer::eFreezeTintChanged; - s->tint = tint; - unlockLayerState(); - return NO_ERROR; -} - // ---------------------------------------------------------------------------- ScreenshotClient::ScreenshotClient() diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp index dfa9211af..c06400e52 100644 --- a/libs/gui/tests/SurfaceTexture_test.cpp +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -84,10 +84,10 @@ protected: ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); - ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction()); + SurfaceComposerClient::openGlobalTransaction(); ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction()); + SurfaceComposerClient::closeGlobalTransaction(); sp window = mSurfaceControl->getSurface(); mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 35c864055..450cdf1f8 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -36,10 +36,10 @@ protected: ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); - ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction()); + SurfaceComposerClient::openGlobalTransaction(); ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000)); ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); - ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction()); + SurfaceComposerClient::closeGlobalTransaction(); mSurface = mSurfaceControl->getSurface(); ASSERT_TRUE(mSurface != NULL); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f0b19f26e..1c57bc1a5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -78,7 +78,6 @@ const String16 sDump("android.permission.DUMP"); SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), - mTransactionCount(0), mResizeTransationPending(false), mLayersRemoved(false), mBootTime(systemTime()), @@ -385,13 +384,11 @@ bool SurfaceFlinger::threadLoop() handleConsoleEvents(); } - 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); - if (LIKELY(transactionFlags)) { - handleTransaction(transactionFlags); - } + // if we're in a global transaction, don't do anything. + const uint32_t mask = eTransactionNeeded | eTraversalNeeded; + uint32_t transactionFlags = peekTransactionFlags(mask); + if (UNLIKELY(transactionFlags)) { + handleTransaction(transactionFlags); } // post surfaces (if needed) @@ -1176,28 +1173,33 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) return old; } -void SurfaceFlinger::openGlobalTransaction() -{ - android_atomic_inc(&mTransactionCount); -} -void SurfaceFlinger::closeGlobalTransaction() -{ - if (android_atomic_dec(&mTransactionCount) == 1) { - signalEvent(); +void SurfaceFlinger::setTransactionState(const Vector& state) { + Mutex::Autolock _l(mStateLock); - // if there is a transaction with a resize, wait for it to - // take effect before returning. - Mutex::Autolock _l(mStateLock); - while (mResizeTransationPending) { - status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); - if (CC_UNLIKELY(err != NO_ERROR)) { - // just in case something goes wrong in SF, return to the - // called after a few seconds. - LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); - mResizeTransationPending = false; - break; - } + uint32_t flags = 0; + const size_t count = state.size(); + for (size_t i=0 ; i client( static_cast(s.client.get()) ); + flags |= setClientStateLocked(client, s.state); + } + if (flags) { + setTransactionFlags(flags); + } + + signalEvent(); + + // if there is a transaction with a resize, wait for it to + // take effect before returning. + while (mResizeTransationPending) { + status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); + if (CC_UNLIKELY(err != NO_ERROR)) { + // just in case something goes wrong in SF, return to the + // called after a few seconds. + LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); + mResizeTransationPending = false; + break; } } } @@ -1393,60 +1395,52 @@ status_t SurfaceFlinger::destroySurface(const wp& layer) return err; } -status_t SurfaceFlinger::setClientState( +uint32_t SurfaceFlinger::setClientStateLocked( const sp& client, - int32_t count, - const layer_state_t* states) + const layer_state_t& s) { - Mutex::Autolock _l(mStateLock); uint32_t flags = 0; - for (int i=0 ; i layer(client->getLayerUser(s.surface)); - if (layer != 0) { - const uint32_t what = s.what; - if (what & ePositionChanged) { - if (layer->setPosition(s.x, s.y)) - flags |= eTraversalNeeded; - } - if (what & eLayerChanged) { - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayer(s.z)) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - if (what & eSizeChanged) { - if (layer->setSize(s.w, s.h)) { - flags |= eTraversalNeeded; - mResizeTransationPending = true; - } - } - if (what & eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) - flags |= eTraversalNeeded; - } - if (what & eMatrixChanged) { - if (layer->setMatrix(s.matrix)) - flags |= eTraversalNeeded; - } - if (what & eTransparentRegionChanged) { - if (layer->setTransparentRegionHint(s.transparentRegion)) - flags |= eTraversalNeeded; - } - if (what & eVisibilityChanged) { - if (layer->setFlags(s.flags, s.mask)) - flags |= eTraversalNeeded; + sp layer(client->getLayerUser(s.surface)); + if (layer != 0) { + const uint32_t what = s.what; + if (what & ePositionChanged) { + if (layer->setPosition(s.x, s.y)) + flags |= eTraversalNeeded; + } + if (what & eLayerChanged) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setLayer(s.z)) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; } } + if (what & eSizeChanged) { + if (layer->setSize(s.w, s.h)) { + flags |= eTraversalNeeded; + mResizeTransationPending = true; + } + } + if (what & eAlphaChanged) { + if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) + flags |= eTraversalNeeded; + } + if (what & eMatrixChanged) { + if (layer->setMatrix(s.matrix)) + flags |= eTraversalNeeded; + } + if (what & eTransparentRegionChanged) { + if (layer->setTransparentRegionHint(s.transparentRegion)) + flags |= eTraversalNeeded; + } + if (what & eVisibilityChanged) { + if (layer->setFlags(s.flags, s.mask)) + flags |= eTraversalNeeded; + } } - if (flags) { - setTransactionFlags(flags); - } - return NO_ERROR; + return flags; } void SurfaceFlinger::screenReleased(int dpy) @@ -1588,8 +1582,7 @@ status_t SurfaceFlinger::onTransact( { switch (code) { case CREATE_CONNECTION: - case OPEN_GLOBAL_TRANSACTION: - case CLOSE_GLOBAL_TRANSACTION: + case SET_TRANSACTION_STATE: case SET_ORIENTATION: case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: @@ -2469,9 +2462,6 @@ sp Client::createSurface( status_t Client::destroySurface(SurfaceID sid) { return mFlinger->removeSurface(this, sid); } -status_t Client::setState(int32_t count, const layer_state_t* states) { - return mFlinger->setClientState(this, count, states); -} // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 45f80aedc..b49fa363e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -70,14 +70,12 @@ public: sp getLayerUser(int32_t i) const; private: - // ISurfaceComposerClient interface virtual sp createSurface( surface_data_t* params, 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); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); @@ -168,8 +166,7 @@ public: virtual sp createGraphicBufferAlloc(); virtual sp getCblk() const; virtual void bootFinished(); - virtual void openGlobalTransaction(); - virtual void closeGlobalTransaction(); + virtual void setTransactionState(const Vector& state); virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags); virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); @@ -220,8 +217,7 @@ private: status_t removeSurface(const sp& client, SurfaceID sid); status_t destroySurface(const wp& layer); - status_t setClientState(const sp& client, - int32_t count, const layer_state_t* states); + uint32_t setClientStateLocked(const sp& client, const layer_state_t& s); class LayerVector : public SortedVector< sp > { public: @@ -337,7 +333,6 @@ private: mutable Mutex mStateLock; State mCurrentState; volatile int32_t mTransactionFlags; - volatile int32_t mTransactionCount; Condition mTransactionCV; SortedVector< sp > mLayerPurgatory; bool mResizeTransationPending; diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp index 18c54b3f8..56b2a8f1c 100644 --- a/services/surfaceflinger/tests/resize/resize.cpp +++ b/services/surfaceflinger/tests/resize/resize.cpp @@ -43,9 +43,9 @@ int main(int argc, char** argv) PIXEL_FORMAT_RGB_565); - client->openTransaction(); + SurfaceComposerClient::openGlobalTransaction(); surface->setLayer(100000); - client->closeTransaction(); + SurfaceComposerClient::closeGlobalTransaction(); Surface::SurfaceInfo info; surface->lock(&info); @@ -57,9 +57,9 @@ int main(int argc, char** argv) android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h); surface->unlockAndPost(); - client->openTransaction(); + SurfaceComposerClient::openGlobalTransaction(); surface->setSize(320, 240); - client->closeTransaction(); + SurfaceComposerClient::closeGlobalTransaction(); IPCThreadState::self()->joinThreadPool(); diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp index 5265f9195..8e1c3fe32 100644 --- a/services/surfaceflinger/tests/surface/surface.cpp +++ b/services/surfaceflinger/tests/surface/surface.cpp @@ -39,9 +39,9 @@ int main(int argc, char** argv) sp surfaceControl = client->createSurface( getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565); - client->openTransaction(); + SurfaceComposerClient::openGlobalTransaction(); surfaceControl->setLayer(100000); - client->closeTransaction(); + SurfaceComposerClient::closeGlobalTransaction(); // pretend it went cross-process Parcel parcel;