From e57f292595bec48f65c8088b00ff6beea01217e9 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 9 Aug 2012 16:29:12 -0700 Subject: [PATCH] make multi-display more real - displays are represented by a binder on the client side - c++ clients can now create and modify displays Change-Id: I203ea5b4beae0819d742ec5171c27568f4e8354b --- include/gui/ISurfaceComposer.h | 40 ++- include/gui/SurfaceComposerClient.h | 26 +- include/private/gui/LayerState.h | 21 +- libs/gui/ISurfaceComposer.cpp | 30 +++ libs/gui/LayerState.cpp | 6 +- libs/gui/SurfaceComposerClient.cpp | 161 +++++++++--- services/surfaceflinger/DisplayDevice.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 292 ++++++++++++++------- services/surfaceflinger/SurfaceFlinger.h | 16 +- 9 files changed, 426 insertions(+), 169 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index b2f888991..9ab35b1b6 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -48,6 +48,11 @@ public: eSynchronous = 0x01, }; + enum { + eDisplayIdMain = 0, + eDisplayIdHdmi = 1 + }; + /* create connection with surface flinger, requires * ACCESS_SURFACE_FLINGER permission */ @@ -57,6 +62,19 @@ public: */ virtual sp createGraphicBufferAlloc() = 0; + /* return an IDisplayEventConnection */ + virtual sp createDisplayEventConnection() = 0; + + /* create a display with given id. + * requires ACCESS_SURFACE_FLINGER permission. + */ + virtual sp createDisplay() = 0; + + /* get the token for the existing default displays. possible values + * for id are eDisplayIdMain and eDisplayIdHdmi. + */ + virtual sp getBuiltInDisplay(int32_t id) = 0; + /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags) = 0; @@ -66,6 +84,11 @@ public: */ virtual void bootFinished() = 0; + /* verify that an ISurfaceTexture was created by SurfaceFlinger. + */ + virtual bool authenticateSurfaceTexture( + const sp& surface) const = 0; + /* Capture the specified screen. requires READ_FRAME_BUFFER permission * This function will fail if there is a secure window on screen. */ @@ -74,13 +97,6 @@ public: uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) = 0; - /* verify that an ISurfaceTexture was created by SurfaceFlinger. - */ - virtual bool authenticateSurfaceTexture( - const sp& surface) const = 0; - - /* return an IDisplayEventConnection */ - virtual sp createDisplayEventConnection() = 0; /* triggers screen off and waits for it to complete */ virtual void blank() = 0; @@ -106,13 +122,15 @@ public: BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, CREATE_GRAPHIC_BUFFER_ALLOC, - GET_DISPLAY_INFO, - SET_TRANSACTION_STATE, - CAPTURE_SCREEN, - AUTHENTICATE_SURFACE, CREATE_DISPLAY_EVENT_CONNECTION, + CREATE_DISPLAY, + GET_BUILT_IN_DISPLAY, + SET_TRANSACTION_STATE, + AUTHENTICATE_SURFACE, + CAPTURE_SCREEN, BLANK, UNBLANK, + GET_DISPLAY_INFO, CONNECT_DISPLAY, }; diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index b058b8dad..5776038c7 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -59,6 +59,13 @@ public: // Forcibly remove connection before all references have gone away. void dispose(); + // callback when the composer is dies + status_t linkToComposerDeath(const sp& recipient, + void* cookie = NULL, uint32_t flags = 0); + + // Get information about a display + static status_t getDisplayInfo(DisplayID dpy, DisplayInfo* info); + // ------------------------------------------------------------------------ // surface creation / destruction @@ -80,13 +87,14 @@ public: uint32_t flags = 0 // usage flags ); + static sp createDisplay(); // ------------------------------------------------------------------------ // Composer parameters // 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. - // closeGlobalTransaction() usually requires an IPC with the server. + // closeGlobalTransaction() requires an IPC with the server. //! Open a composer transaction on all active SurfaceComposerClients. static void openGlobalTransaction(); @@ -97,12 +105,6 @@ public: //! Set the orientation of the given display static int setOrientation(DisplayID dpy, int orientation, uint32_t flags); - // Get information about a display - static status_t getDisplayInfo(DisplayID dpy, DisplayInfo* info); - - status_t linkToComposerDeath(const sp& recipient, - void* cookie = NULL, uint32_t flags = 0); - status_t hide(SurfaceID id); status_t show(SurfaceID id, int32_t layer = -1); status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask); @@ -116,6 +118,16 @@ public: status_t setLayerStack(SurfaceID id, uint32_t layerStack); status_t destroySurface(SurfaceID sid); + static void setDisplaySurface(const sp& token, + const sp& surface); + static void setDisplayLayerStack(const sp& token, + uint32_t layerStack); + static void setDisplayOrientation(const sp& token, + uint32_t orientation); + static void setDisplayViewport(const sp& token, + const Rect& viewport); + static void setDisplayFrame(const sp& token, const Rect& frame); + private: virtual void onFirstRef(); Composer& getComposer(); diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index 90e74a9ea..9765e2816 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -106,14 +106,21 @@ struct DisplayState { eOrientationSwapMask = 0x01 }; - int32_t displayId; + enum { + eSurfaceChanged = 0x1, + eLayerStackChanged = 0x2, + eTransformChanged = 0x4 + }; + + uint32_t what; + sp token; sp surface; - uint32_t layerStack; - uint32_t orientation; - Rect viewport; - Rect frame; - status_t write(Parcel& output) const; - status_t read(const Parcel& input); + uint32_t layerStack; + uint32_t orientation; + Rect viewport; + Rect frame; + status_t write(Parcel& output) const; + status_t read(const Parcel& input); }; }; // namespace android diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 5d8f1a109..76b23f33a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -179,6 +179,23 @@ public: return result; } + virtual sp createDisplay() + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply); + return reply.readStrongBinder(); + } + + virtual sp getBuiltInDisplay(int32_t id) + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeInt32(id); + remote()->transact(BnSurfaceComposer::GET_BUILT_IN_DISPLAY, data, &reply); + return reply.readStrongBinder(); + } + virtual void blank() { Parcel data, reply; @@ -286,6 +303,19 @@ status_t BnSurfaceComposer::onTransact( reply->writeStrongBinder(connection->asBinder()); return NO_ERROR; } break; + case CREATE_DISPLAY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp display(createDisplay()); + reply->writeStrongBinder(display); + return NO_ERROR; + } break; + case GET_BUILT_IN_DISPLAY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int32_t id = data.readInt32(); + sp display(getBuiltInDisplay(id)); + reply->writeStrongBinder(display); + return NO_ERROR; + } break; case BLANK: { CHECK_INTERFACE(ISurfaceComposer, data, reply); blank(); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 25c773c3a..07f62c40e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -72,8 +72,9 @@ status_t ComposerState::read(const Parcel& input) { status_t DisplayState::write(Parcel& output) const { + output.writeStrongBinder(token); output.writeStrongBinder(surface->asBinder()); - output.writeInt32(displayId); + output.writeInt32(what); output.writeInt32(layerStack); output.writeInt32(orientation); memcpy(output.writeInplace(sizeof(Rect)), &viewport, sizeof(Rect)); @@ -82,8 +83,9 @@ status_t DisplayState::write(Parcel& output) const { } status_t DisplayState::read(const Parcel& input) { + token = input.readStrongBinder(); surface = interface_cast(input.readStrongBinder()); - displayId = input.readInt32(); + what = input.readInt32(); layerStack = input.readInt32(); orientation = input.readInt32(); memcpy(&viewport, input.readInplace(sizeof(Rect)), sizeof(Rect)); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 7f42a3497..db86d4a41 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -56,16 +56,10 @@ sp ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService; } -static inline sp getComposerService() { - return ComposerService::getComposerService(); -} - // --------------------------------------------------------------------------- -// 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) { +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; @@ -73,17 +67,21 @@ int compare_type( const ComposerState& lhs, const ComposerState& rhs) { return 0; } +static inline +int compare_type(const DisplayState& lhs, const DisplayState& rhs) { + return compare_type(lhs.token, rhs.token); +} + class Composer : public Singleton { friend class Singleton; mutable Mutex mLock; - SortedVector mStates; - int mOrientation; + SortedVector mComposerStates; + SortedVector mDisplayStates; uint32_t mForceSynchronous; Composer() : Singleton(), - mOrientation(DisplayState::eOrientationUnchanged), mForceSynchronous(0) { } @@ -92,7 +90,10 @@ class Composer : public Singleton layer_state_t* getLayerStateLocked( const sp& client, SurfaceID id); + DisplayState& getDisplayStateLocked(const sp& token); + public: + sp createDisplay(); status_t setPosition(const sp& client, SurfaceID id, float x, float y); @@ -115,6 +116,12 @@ public: status_t setLayerStack(const sp& client, SurfaceID id, uint32_t layerStack); + void setDisplaySurface(const sp& token, const sp& surface); + void setDisplayLayerStack(const sp& token, uint32_t layerStack); + void setDisplayOrientation(const sp& token, uint32_t orientation); + void setDisplayViewport(const sp& token, const Rect& viewport); + void setDisplayFrame(const sp& token, const Rect& frame); + static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(synchronous); } @@ -124,8 +131,12 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- +sp Composer::createDisplay() { + return ComposerService::getComposerService()->createDisplay(); +} + void Composer::closeGlobalTransactionImpl(bool synchronous) { - sp sm(getComposerService()); + sp sm(ComposerService::getComposerService()); Vector transaction; Vector displayTransaction; @@ -133,15 +144,11 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) { { // scope for the lock Mutex::Autolock _l(mLock); - transaction = mStates; - mStates.clear(); + transaction = mComposerStates; + mComposerStates.clear(); - // FIXME: this should be the displays transaction state here - DisplayState item; - item.orientation = mOrientation; - displayTransaction.add(item); - - mOrientation = DisplayState::eOrientationUnchanged; + displayTransaction = mDisplayStates; + mDisplayStates.clear(); if (synchronous || mForceSynchronous) { flags |= ISurfaceComposer::eSynchronous; @@ -159,13 +166,13 @@ layer_state_t* Composer::getLayerStateLocked( s.client = client->mClient; s.state.surface = id; - ssize_t index = mStates.indexOf(s); + ssize_t index = mComposerStates.indexOf(s); if (index < 0) { // we don't have it, add an initialized layer_state to our list - index = mStates.add(s); + index = mComposerStates.add(s); } - ComposerState* const out = mStates.editArray(); + ComposerState* const out = mComposerStates.editArray(); return &(out[index].state); } @@ -273,16 +280,6 @@ status_t Composer::setMatrix(const sp& client, return NO_ERROR; } -status_t Composer::setOrientation(int orientation) { - Mutex::Autolock _l(mLock); - mOrientation = orientation; - - // Changing the orientation makes the transaction synchronous. - mForceSynchronous = true; - - return NO_ERROR; -} - status_t Composer::setCrop(const sp& client, SurfaceID id, const Rect& crop) { Mutex::Autolock _l(mLock); @@ -296,13 +293,76 @@ status_t Composer::setCrop(const sp& client, // --------------------------------------------------------------------------- +DisplayState& Composer::getDisplayStateLocked(const sp& token) { + DisplayState s; + s.token = token; + ssize_t index = mDisplayStates.indexOf(s); + if (index < 0) { + // we don't have it, add an initialized layer_state to our list + s.what = 0; + index = mDisplayStates.add(s); + } + return mDisplayStates.editItemAt(index); +} + +void Composer::setDisplaySurface(const sp& token, + const sp& surface) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.surface = surface; + s.what |= DisplayState::eSurfaceChanged; +} + +void Composer::setDisplayLayerStack(const sp& token, + uint32_t layerStack) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.layerStack = layerStack; + s.what |= DisplayState::eLayerStackChanged; +} + +void Composer::setDisplayOrientation(const sp& token, + uint32_t orientation) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.orientation = orientation; + s.what |= DisplayState::eTransformChanged; + mForceSynchronous = true; // TODO: do we actually still need this? +} + +// FIXME: get rid of this eventually +status_t Composer::setOrientation(int orientation) { + sp sm(ComposerService::getComposerService()); + sp token(sm->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + Composer::setDisplayOrientation(token, orientation); + return NO_ERROR; +} + +void Composer::setDisplayViewport(const sp& token, + const Rect& viewport) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.viewport = viewport; + s.what |= DisplayState::eTransformChanged; +} + +void Composer::setDisplayFrame(const sp& token, + const Rect& frame) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.frame = frame; + s.what |= DisplayState::eTransformChanged; +} + +// --------------------------------------------------------------------------- + SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT), mComposer(Composer::getInstance()) { } void SurfaceComposerClient::onFirstRef() { - sp sm(getComposerService()); + sp sm(ComposerService::getComposerService()); if (sm != 0) { sp conn = sm->createConnection(); if (conn != 0) { @@ -327,7 +387,7 @@ sp SurfaceComposerClient::connection() const { status_t SurfaceComposerClient::linkToComposerDeath( const sp& recipient, void* cookie, uint32_t flags) { - sp sm(getComposerService()); + sp sm(ComposerService::getComposerService()); return sm->asBinder()->linkToDeath(recipient, cookie, flags); } @@ -379,6 +439,10 @@ sp SurfaceComposerClient::createSurface( return result; } +sp SurfaceComposerClient::createDisplay() { + return Composer::getInstance().createDisplay(); +} + status_t SurfaceComposerClient::destroySurface(SurfaceID sid) { if (mStatus != NO_ERROR) return mStatus; @@ -461,10 +525,37 @@ status_t SurfaceComposerClient::setOrientation(DisplayID dpy, // ---------------------------------------------------------------------------- +void SurfaceComposerClient::setDisplaySurface(const sp& token, + const sp& surface) { + Composer::getInstance().setDisplaySurface(token, surface); +} + +void SurfaceComposerClient::setDisplayLayerStack(const sp& token, + uint32_t layerStack) { + Composer::getInstance().setDisplayLayerStack(token, layerStack); +} + +void SurfaceComposerClient::setDisplayOrientation(const sp& token, + uint32_t orientation) { + Composer::getInstance().setDisplayOrientation(token, orientation); +} + +void SurfaceComposerClient::setDisplayViewport(const sp& token, + const Rect& viewport) { + Composer::getInstance().setDisplayViewport(token, viewport); +} + +void SurfaceComposerClient::setDisplayFrame(const sp& token, + const Rect& frame) { + Composer::getInstance().setDisplayFrame(token, frame); +} + +// ---------------------------------------------------------------------------- + status_t SurfaceComposerClient::getDisplayInfo( DisplayID dpy, DisplayInfo* info) { - return getComposerService()->getDisplayInfo(dpy, info); + return ComposerService::getComposerService()->getDisplayInfo(dpy, info); } // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index cb8fe2fc8..0229dad62 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -51,7 +51,8 @@ public: enum { DISPLAY_ID_MAIN = 0, - DISPLAY_ID_HDMI = 1 + DISPLAY_ID_HDMI = 1, + DISPLAY_ID_COUNT }; enum { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ac3fb90f8..f2b49e8b6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -161,6 +161,39 @@ sp SurfaceFlinger::createConnection() return bclient; } +sp SurfaceFlinger::createDisplay() +{ + class DisplayToken : public BBinder { + sp flinger; + virtual ~DisplayToken() { + // no more references, this display must be terminated + Mutex::Autolock _l(flinger->mStateLock); + flinger->mCurrentState.displays.removeItem(this); + flinger->setTransactionFlags(eDisplayTransactionNeeded); + } + public: + DisplayToken(const sp& flinger) + : flinger(flinger) { + } + }; + + sp token = new DisplayToken(this); + + Mutex::Autolock _l(mStateLock); + DisplayDeviceState info(intptr_t(token.get())); // FIXME: we shouldn't use the address for the id + mCurrentState.displays.add(token, info); + + return token; +} + +sp SurfaceFlinger::getBuiltInDisplay(int32_t id) { + if (uint32_t(id) >= DisplayDevice::DISPLAY_ID_COUNT) { + ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id); + return NULL; + } + return mDefaultDisplays[id]; +} + sp SurfaceFlinger::createGraphicBufferAlloc() { sp gba(new GraphicBufferAlloc()); @@ -358,7 +391,8 @@ status_t SurfaceFlinger::readyToRun() exit(0); } - sp stc(new SurfaceTextureClient(static_cast >(fbs->getBufferQueue()))); + sp stc(new SurfaceTextureClient( + static_cast >(fbs->getBufferQueue()))); // initialize the config and context int format; @@ -368,9 +402,14 @@ status_t SurfaceFlinger::readyToRun() mEGLContext = createGLContext(mEGLDisplay, mEGLConfig); // initialize our main display hardware - mCurrentState.displays.add(DisplayDevice::DISPLAY_ID_MAIN, DisplayDeviceState()); - sp hw = new DisplayDevice(this, DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig); - mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw); + + for (size_t i=0 ; i hw = new DisplayDevice(this, + DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig); + mDisplays.add(hw->getDisplayId(), hw); // initialize OpenGL ES EGLSurface surface = hw->getEGLSurface(); @@ -571,8 +610,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { } void SurfaceFlinger::handleMessageTransaction() { - const uint32_t mask = eTransactionNeeded | eTraversalNeeded; - uint32_t transactionFlags = peekTransactionFlags(mask); + uint32_t transactionFlags = peekTransactionFlags(eTransactionMask); if (transactionFlags) { handleTransaction(transactionFlags); } @@ -795,8 +833,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) // with mStateLock held to guarantee that mCurrentState won't change // until the transaction is committed. - const uint32_t mask = eTransactionNeeded | eTraversalNeeded; - transactionFlags = getTransactionFlags(mask); + transactionFlags = getTransactionFlags(eTransactionMask); handleTransactionLocked(transactionFlags); mLastTransactionTime = systemTime() - now; @@ -832,12 +869,12 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) * Perform our own transaction if needed */ - if (transactionFlags & eTransactionNeeded) { + if (transactionFlags & eDisplayTransactionNeeded) { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical - const KeyedVector& curr(mCurrentState.displays); - const KeyedVector& draw(mDrawingState.displays); + const KeyedVector< wp, DisplayDeviceState>& curr(mCurrentState.displays); + const KeyedVector< wp, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; const size_t cc = curr.size(); @@ -848,7 +885,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i=0 ; i stc( + new SurfaceTextureClient(state.surface)); + + sp disp = new DisplayDevice(this, + state.id, stc, 0, mEGLConfig); + + disp->setLayerStack(state.layerStack); + disp->setOrientation(state.orientation); + // TODO: take viewport and frame into account + mDisplays.replaceValueFor(state.id, disp); + } if (state.layerStack != draw[i].layerStack) { const sp& disp(getDisplayDevice(state.id)); disp->setLayerStack(state.layerStack); } - if (curr[i].orientation != draw[i].orientation) { + if (state.orientation != draw[i].orientation || + state.viewport != draw[i].viewport || + state.frame != draw[i].frame) { const sp& disp(getDisplayDevice(state.id)); disp->setOrientation(state.orientation); + // TODO: take viewport and frame into account } } } @@ -872,10 +928,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // find displays that were added // (ie: in current state but not in drawing state) for (size_t i=0 ; i disp = new DisplayDevice(this, curr[i].id, 0, 0, mEGLConfig); - mDisplays.add(curr[i].id, disp); + const DisplayDeviceState& state(curr[i]); + sp stc( + new SurfaceTextureClient(state.surface)); + sp disp = new DisplayDevice(this, state.id, + stc, 0, mEGLConfig); + mDisplays.add(state.id, disp); } } } @@ -1358,33 +1418,21 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) return old; } - void SurfaceFlinger::setTransactionState( const Vector& state, const Vector& displays, uint32_t flags) { Mutex::Autolock _l(mStateLock); - - int orientation = DisplayState::eOrientationUnchanged; - if (displays.size()) { - // TODO: handle all displays - orientation = displays[0].orientation; - } - uint32_t transactionFlags = 0; - // FIXME: don't hardcode display id here - if (mCurrentState.displays.valueFor(0).orientation != orientation) { - if (uint32_t(orientation) <= DisplayState::eOrientation270) { - mCurrentState.displays.editValueFor(0).orientation = orientation; - transactionFlags |= eTransactionNeeded; - } else if (orientation != DisplayState::eOrientationUnchanged) { - ALOGW("setTransactionState: ignoring unrecognized orientation: %d", - orientation); - } + + size_t count = displays.size(); + for (size_t i=0 ; i client( static_cast(s.client.get()) ); @@ -1413,6 +1461,105 @@ void SurfaceFlinger::setTransactionState( } } +uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) +{ + uint32_t flags = 0; + DisplayDeviceState& disp(mCurrentState.displays.editValueFor(s.token)); + if (disp.id >= 0) { + const uint32_t what = s.what; + if (what & DisplayState::eSurfaceChanged) { + if (disp.surface->asBinder() != s.surface->asBinder()) { + disp.surface = s.surface; + flags |= eDisplayTransactionNeeded; + } + } + if (what & DisplayState::eLayerStackChanged) { + if (disp.layerStack != s.layerStack) { + disp.layerStack = s.layerStack; + flags |= eDisplayTransactionNeeded; + } + } + if (what & DisplayState::eTransformChanged) { + if (disp.orientation != s.orientation) { + disp.orientation = s.orientation; + flags |= eDisplayTransactionNeeded; + } + if (disp.frame != s.frame) { + disp.frame = s.frame; + flags |= eDisplayTransactionNeeded; + } + if (disp.viewport != s.viewport) { + disp.viewport = s.viewport; + flags |= eDisplayTransactionNeeded; + } + } + } + return flags; +} + +uint32_t SurfaceFlinger::setClientStateLocked( + const sp& client, + const layer_state_t& s) +{ + uint32_t flags = 0; + sp layer(client->getLayerUser(s.surface)); + if (layer != 0) { + const uint32_t what = s.what; + if (what & layer_state_t::ePositionChanged) { + if (layer->setPosition(s.x, s.y)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eLayerChanged) { + // NOTE: index needs to be calculated before we update the state + 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 & layer_state_t::eSizeChanged) { + if (layer->setSize(s.w, s.h)) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eAlphaChanged) { + if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eMatrixChanged) { + if (layer->setMatrix(s.matrix)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eTransparentRegionChanged) { + if (layer->setTransparentRegionHint(s.transparentRegion)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eVisibilityChanged) { + if (layer->setFlags(s.flags, s.mask)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eCropChanged) { + if (layer->setCrop(s.crop)) + flags |= eTraversalNeeded; + } + if (what & layer_state_t::eLayerStackChanged) { + // NOTE: index needs to be calculated before we update the state + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setLayerStack(s.layerStack)) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; + } + } + } + return flags; +} + sp SurfaceFlinger::createLayer( ISurfaceComposerClient::surface_data_t* params, const String8& name, @@ -1554,69 +1701,6 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp& layer) return err; } -uint32_t SurfaceFlinger::setClientStateLocked( - const sp& client, - const layer_state_t& s) -{ - uint32_t flags = 0; - sp layer(client->getLayerUser(s.surface)); - if (layer != 0) { - const uint32_t what = s.what; - if (what & layer_state_t::ePositionChanged) { - if (layer->setPosition(s.x, s.y)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eLayerChanged) { - // NOTE: index needs to be calculated before we update the state - 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 & layer_state_t::eSizeChanged) { - if (layer->setSize(s.w, s.h)) { - flags |= eTraversalNeeded; - } - } - if (what & layer_state_t::eAlphaChanged) { - if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f))) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eMatrixChanged) { - if (layer->setMatrix(s.matrix)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eTransparentRegionChanged) { - if (layer->setTransparentRegionHint(s.transparentRegion)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eVisibilityChanged) { - if (layer->setFlags(s.flags, s.mask)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eCropChanged) { - if (layer->setCrop(s.crop)) - flags |= eTraversalNeeded; - } - if (what & layer_state_t::eLayerStackChanged) { - // NOTE: index needs to be calculated before we update the state - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayerStack(s.layerStack)) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; - } - } - } - return flags; -} - // --------------------------------------------------------------------------- void SurfaceFlinger::onScreenAcquired() { @@ -1964,7 +2048,10 @@ status_t SurfaceFlinger::onTransact( return NO_ERROR; } case 1005:{ // force transaction - setTransactionFlags(eTransactionNeeded|eTraversalNeeded); + setTransactionFlags( + eTransactionNeeded| + eDisplayTransactionNeeded| + eTraversalNeeded); return NO_ERROR; } case 1006:{ // send empty update @@ -2305,8 +2392,11 @@ int SurfaceFlinger::LayerVector::do_compare(const void* lhs, // --------------------------------------------------------------------------- -SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() - : id(DisplayDevice::DISPLAY_ID_MAIN), layerStack(0), orientation(0) { +SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() : id(-1) { +} + +SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(int32_t id) + : id(id), layerStack(0), orientation(0) { } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index da417ffd0..6438beebd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -78,7 +78,10 @@ public: // --------------------------------------------------------------------------- enum { - eTransactionNeeded = 0x01, eTraversalNeeded = 0x02 + eTransactionNeeded = 0x01, + eTraversalNeeded = 0x02, + eDisplayTransactionNeeded = 0x04, + eTransactionMask = 0x07 }; class SurfaceFlinger : public BinderService, @@ -158,19 +161,18 @@ private: struct DisplayDeviceState { DisplayDeviceState(); + DisplayDeviceState(int32_t id); int32_t id; + sp surface; uint32_t layerStack; Rect viewport; Rect frame; uint8_t orientation; - inline bool operator < (const DisplayDeviceState& rhs) const { - return id < rhs.id; - } }; struct State { LayerVector layersSortedByZ; - KeyedVector displays; + DefaultKeyedVector< wp, DisplayDeviceState> displays; }; /* ------------------------------------------------------------------------ @@ -185,6 +187,8 @@ private: */ virtual sp createConnection(); virtual sp createGraphicBufferAlloc(); + virtual sp createDisplay(); + virtual sp getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector& state, const Vector& displays, uint32_t flags); virtual void bootFinished(); @@ -256,6 +260,7 @@ private: void commitTransaction(); uint32_t setClientStateLocked(const sp& client, const layer_state_t& s); + uint32_t setDisplayStateLocked(const DisplayState& s); /* ------------------------------------------------------------------------ * Layer management @@ -391,6 +396,7 @@ private: EGLContext mEGLContext; EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; + sp mDefaultDisplays[DisplayDevice::DISPLAY_ID_COUNT]; // Can only accessed from the main thread, these members // don't need synchronization