diff options
-rw-r--r-- | include/gui/ISurfaceComposer.h | 38 | ||||
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 26 | ||||
-rw-r--r-- | include/private/gui/LayerState.h | 21 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 30 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 6 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 161 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 292 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 16 |
9 files changed, 425 insertions, 168 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index b2f8889..9ab35b1 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<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0; + /* return an IDisplayEventConnection */ + virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0; + + /* create a display with given id. + * requires ACCESS_SURFACE_FLINGER permission. + */ + virtual sp<IBinder> createDisplay() = 0; + + /* get the token for the existing default displays. possible values + * for id are eDisplayIdMain and eDisplayIdHdmi. + */ + virtual sp<IBinder> getBuiltInDisplay(int32_t id) = 0; + /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual void setTransactionState(const Vector<ComposerState>& state, const Vector<DisplayState>& 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<ISurfaceTexture>& 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<ISurfaceTexture>& surface) const = 0; - - /* return an IDisplayEventConnection */ - virtual sp<IDisplayEventConnection> 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, + CREATE_DISPLAY_EVENT_CONNECTION, + CREATE_DISPLAY, + GET_BUILT_IN_DISPLAY, SET_TRANSACTION_STATE, - CAPTURE_SCREEN, AUTHENTICATE_SURFACE, - CREATE_DISPLAY_EVENT_CONNECTION, + CAPTURE_SCREEN, BLANK, UNBLANK, + GET_DISPLAY_INFO, CONNECT_DISPLAY, }; diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index b058b8d..5776038 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<IBinder::DeathRecipient>& 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<IBinder> 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<IBinder::DeathRecipient>& 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<IBinder>& token, + const sp<ISurfaceTexture>& surface); + static void setDisplayLayerStack(const sp<IBinder>& token, + uint32_t layerStack); + static void setDisplayOrientation(const sp<IBinder>& token, + uint32_t orientation); + static void setDisplayViewport(const sp<IBinder>& token, + const Rect& viewport); + static void setDisplayFrame(const sp<IBinder>& 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 90e74a9..9765e28 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<IBinder> token; sp<ISurfaceTexture> 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 5d8f1a1..76b23f3 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -179,6 +179,23 @@ public: return result; } + virtual sp<IBinder> createDisplay() + { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + remote()->transact(BnSurfaceComposer::CREATE_DISPLAY, data, &reply); + return reply.readStrongBinder(); + } + + virtual sp<IBinder> 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<IBinder> 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<IBinder> 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 25c773c..07f62c4 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<ISurfaceTexture>(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 7f42a34..db86d4a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -56,16 +56,10 @@ sp<ISurfaceComposer> ComposerService::getComposerService() { return ComposerService::getInstance().mComposerService; } -static inline sp<ISurfaceComposer> 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<Composer> { friend class Singleton<Composer>; mutable Mutex mLock; - SortedVector<ComposerState> mStates; - int mOrientation; + SortedVector<ComposerState> mComposerStates; + SortedVector<DisplayState > mDisplayStates; uint32_t mForceSynchronous; Composer() : Singleton<Composer>(), - mOrientation(DisplayState::eOrientationUnchanged), mForceSynchronous(0) { } @@ -92,7 +90,10 @@ class Composer : public Singleton<Composer> layer_state_t* getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id); + DisplayState& getDisplayStateLocked(const sp<IBinder>& token); + public: + sp<IBinder> createDisplay(); status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id, float x, float y); @@ -115,6 +116,12 @@ public: status_t setLayerStack(const sp<SurfaceComposerClient>& client, SurfaceID id, uint32_t layerStack); + void setDisplaySurface(const sp<IBinder>& token, const sp<ISurfaceTexture>& surface); + void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack); + void setDisplayOrientation(const sp<IBinder>& token, uint32_t orientation); + void setDisplayViewport(const sp<IBinder>& token, const Rect& viewport); + void setDisplayFrame(const sp<IBinder>& token, const Rect& frame); + static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(synchronous); } @@ -124,8 +131,12 @@ ANDROID_SINGLETON_STATIC_INSTANCE(Composer); // --------------------------------------------------------------------------- +sp<IBinder> Composer::createDisplay() { + return ComposerService::getComposerService()->createDisplay(); +} + void Composer::closeGlobalTransactionImpl(bool synchronous) { - sp<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); Vector<ComposerState> transaction; Vector<DisplayState> displayTransaction; @@ -133,15 +144,11 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) { { // scope for the lock Mutex::Autolock _l(mLock); - transaction = mStates; - mStates.clear(); - - // FIXME: this should be the displays transaction state here - DisplayState item; - item.orientation = mOrientation; - displayTransaction.add(item); + transaction = mComposerStates; + mComposerStates.clear(); - 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<SurfaceComposerClient>& 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<SurfaceComposerClient>& client, SurfaceID id, const Rect& crop) { Mutex::Autolock _l(mLock); @@ -296,13 +293,76 @@ status_t Composer::setCrop(const sp<SurfaceComposerClient>& client, // --------------------------------------------------------------------------- +DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& 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<IBinder>& token, + const sp<ISurfaceTexture>& surface) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.surface = surface; + s.what |= DisplayState::eSurfaceChanged; +} + +void Composer::setDisplayLayerStack(const sp<IBinder>& token, + uint32_t layerStack) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.layerStack = layerStack; + s.what |= DisplayState::eLayerStackChanged; +} + +void Composer::setDisplayOrientation(const sp<IBinder>& 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<ISurfaceComposer> sm(ComposerService::getComposerService()); + sp<IBinder> token(sm->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); + Composer::setDisplayOrientation(token, orientation); + return NO_ERROR; +} + +void Composer::setDisplayViewport(const sp<IBinder>& token, + const Rect& viewport) { + Mutex::Autolock _l(mLock); + DisplayState& s(getDisplayStateLocked(token)); + s.viewport = viewport; + s.what |= DisplayState::eTransformChanged; +} + +void Composer::setDisplayFrame(const sp<IBinder>& 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<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); if (sm != 0) { sp<ISurfaceComposerClient> conn = sm->createConnection(); if (conn != 0) { @@ -327,7 +387,7 @@ sp<IBinder> SurfaceComposerClient::connection() const { status_t SurfaceComposerClient::linkToComposerDeath( const sp<IBinder::DeathRecipient>& recipient, void* cookie, uint32_t flags) { - sp<ISurfaceComposer> sm(getComposerService()); + sp<ISurfaceComposer> sm(ComposerService::getComposerService()); return sm->asBinder()->linkToDeath(recipient, cookie, flags); } @@ -379,6 +439,10 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface( return result; } +sp<IBinder> 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<IBinder>& token, + const sp<ISurfaceTexture>& surface) { + Composer::getInstance().setDisplaySurface(token, surface); +} + +void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token, + uint32_t layerStack) { + Composer::getInstance().setDisplayLayerStack(token, layerStack); +} + +void SurfaceComposerClient::setDisplayOrientation(const sp<IBinder>& token, + uint32_t orientation) { + Composer::getInstance().setDisplayOrientation(token, orientation); +} + +void SurfaceComposerClient::setDisplayViewport(const sp<IBinder>& token, + const Rect& viewport) { + Composer::getInstance().setDisplayViewport(token, viewport); +} + +void SurfaceComposerClient::setDisplayFrame(const sp<IBinder>& 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 cb8fe2f..0229dad 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 ac3fb90..f2b49e8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -161,6 +161,39 @@ sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() return bclient; } +sp<IBinder> SurfaceFlinger::createDisplay() +{ + class DisplayToken : public BBinder { + sp<SurfaceFlinger> 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<SurfaceFlinger>& flinger) + : flinger(flinger) { + } + }; + + sp<BBinder> 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<IBinder> 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<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() { sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); @@ -358,7 +391,8 @@ status_t SurfaceFlinger::readyToRun() exit(0); } - sp<SurfaceTextureClient> stc(new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(fbs->getBufferQueue()))); + sp<SurfaceTextureClient> stc(new SurfaceTextureClient( + static_cast<sp<ISurfaceTexture> >(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<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig); - mDisplays.add(DisplayDevice::DISPLAY_ID_MAIN, hw); + + for (size_t i=0 ; i<DisplayDevice::DISPLAY_ID_COUNT ; i++) { + mDefaultDisplays[i] = new BBinder(); + mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i)); + } + sp<DisplayDevice> 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<int32_t, DisplayDeviceState>& curr(mCurrentState.displays); - const KeyedVector<int32_t, DisplayDeviceState>& draw(mDrawingState.displays); + const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); + const KeyedVector< wp<IBinder>, 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<dc ; i++) { - if (curr.indexOfKey(draw[i].id) < 0) { + const ssize_t j = curr.indexOfKey(draw.keyAt(i)); + if (j < 0) { // in drawing state but not in current state if (draw[i].id != DisplayDevice::DISPLAY_ID_MAIN) { mDisplays.removeItem(draw[i].id); @@ -857,14 +895,32 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) } } else { // this display is in both lists. see if something changed. - const DisplayDeviceState& state(curr[i]); + const DisplayDeviceState& state(curr[j]); + if (state.surface != draw[i].surface) { + // changing the surface is like destroying and + // recreating the DisplayDevice + + sp<SurfaceTextureClient> stc( + new SurfaceTextureClient(state.surface)); + + sp<DisplayDevice> 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<DisplayDevice>& 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<DisplayDevice>& 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<cc ; i++) { - if (mDrawingState.displays.indexOfKey(curr[i].id) < 0) { + if (draw.indexOfKey(curr.keyAt(i)) < 0) { // FIXME: we need to pass the surface here - sp<DisplayDevice> disp = new DisplayDevice(this, curr[i].id, 0, 0, mEGLConfig); - mDisplays.add(curr[i].id, disp); + const DisplayDeviceState& state(curr[i]); + sp<SurfaceTextureClient> stc( + new SurfaceTextureClient(state.surface)); + sp<DisplayDevice> 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<ComposerState>& state, const Vector<DisplayState>& 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<count ; i++) { + const DisplayState& s(displays[i]); + transactionFlags |= setDisplayStateLocked(s); } - const size_t count = state.size(); + count = state.size(); for (size_t i=0 ; i<count ; i++) { const ComposerState& s(state[i]); sp<Client> client( static_cast<Client *>(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>& client, + const layer_state_t& s) +{ + uint32_t flags = 0; + sp<LayerBaseClient> 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<ISurface> SurfaceFlinger::createLayer( ISurfaceComposerClient::surface_data_t* params, const String8& name, @@ -1554,69 +1701,6 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer) return err; } -uint32_t SurfaceFlinger::setClientStateLocked( - const sp<Client>& client, - const layer_state_t& s) -{ - uint32_t flags = 0; - sp<LayerBaseClient> 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 da417ff..6438bee 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<SurfaceFlinger>, @@ -158,19 +161,18 @@ private: struct DisplayDeviceState { DisplayDeviceState(); + DisplayDeviceState(int32_t id); int32_t id; + sp<ISurfaceTexture> 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<int32_t, DisplayDeviceState> displays; + DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays; }; /* ------------------------------------------------------------------------ @@ -185,6 +187,8 @@ private: */ virtual sp<ISurfaceComposerClient> createConnection(); virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc(); + virtual sp<IBinder> createDisplay(); + virtual sp<IBinder> getBuiltInDisplay(int32_t id); virtual void setTransactionState(const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags); virtual void bootFinished(); @@ -256,6 +260,7 @@ private: void commitTransaction(); uint32_t setClientStateLocked(const sp<Client>& 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<IBinder> mDefaultDisplays[DisplayDevice::DISPLAY_ID_COUNT]; // Can only accessed from the main thread, these members // don't need synchronization |