diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index a20caf942..5d2d8d705 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -99,10 +99,10 @@ public: /* triggers screen off and waits for it to complete */ - virtual void blank() = 0; + virtual void blank(const sp& display) = 0; /* triggers screen on and waits for it to complete */ - virtual void unblank() = 0; + virtual void unblank(const sp& display) = 0; /* returns information about a display * intended to be used to get information about built-in displays */ diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 07d2b799f..aff1b45ff 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -197,17 +197,19 @@ public: return reply.readStrongBinder(); } - virtual void blank() + virtual void blank(const sp& display) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); remote()->transact(BnSurfaceComposer::BLANK, data, &reply); } - virtual void unblank() + virtual void unblank(const sp& display) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply); } @@ -320,11 +322,13 @@ status_t BnSurfaceComposer::onTransact( } break; case BLANK: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - blank(); + sp display = data.readStrongBinder(); + blank(display); } break; case UNBLANK: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - unblank(); + sp display = data.readStrongBinder(); + unblank(display); } break; case GET_DISPLAY_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 987cc647e..960fb0e10 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -646,17 +646,19 @@ status_t HWComposer::commit() { return (status_t)err; } -status_t HWComposer::release() const { +status_t HWComposer::release(int disp) const { + LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); if (mHwc) { - mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); - return (status_t)mHwc->blank(mHwc, 0, 1); + mHwc->eventControl(mHwc, disp, HWC_EVENT_VSYNC, 0); + return (status_t)mHwc->blank(mHwc, disp, 1); } return NO_ERROR; } -status_t HWComposer::acquire() const { +status_t HWComposer::acquire(int disp) const { + LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); if (mHwc) { - return (status_t)mHwc->blank(mHwc, 0, 0); + return (status_t)mHwc->blank(mHwc, disp, 0); } return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 8f6665165..633ca9c13 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -92,10 +92,10 @@ public: status_t commit(); // release hardware resources and blank screen - status_t release() const; + status_t release(int disp) const; // acquire hardware resources and unblank screen - status_t acquire() const; + status_t acquire(int disp) const; // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED. status_t createWorkList(int32_t id, size_t numLayers); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5f06105e9..8cfaa31a6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -490,11 +490,11 @@ status_t SurfaceFlinger::readyToRun() static_cast< sp >(fbs->getBufferQueue())); sp hw = new DisplayDevice(this, type, token, stc, fbs, mEGLConfig); - if (i > DisplayDevice::DISPLAY_PRIMARY) { - // FIXME: currently we don't really handle blank/unblank + // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always // assume a connected display is unblanked. + ALOGD("marking display %d as acquired/unblanked", i); hw->acquireScreen(); } mDisplays.add(token, hw); @@ -1972,59 +1972,94 @@ void SurfaceFlinger::initializeDisplays() { void SurfaceFlinger::onScreenAcquired(const sp& hw) { - ALOGD("Screen about to return, flinger = %p", this); - getHwComposer().acquire(); + ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this); + if (hw->isScreenAcquired()) { + // this is expected, e.g. when power manager wakes up during boot + ALOGD(" screen was previously acquired"); + return; + } + hw->acquireScreen(); - if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { - // FIXME: eventthread only knows about the main display right now - mEventThread->onScreenAcquired(); + int32_t type = hw->getDisplayType(); + if (type < DisplayDevice::NUM_DISPLAY_TYPES) { + // built-in display, tell the HWC + getHwComposer().acquire(type); + + if (type == DisplayDevice::DISPLAY_PRIMARY) { + // FIXME: eventthread only knows about the main display right now + mEventThread->onScreenAcquired(); + } } mVisibleRegionsDirty = true; repaintEverything(); } void SurfaceFlinger::onScreenReleased(const sp& hw) { - ALOGD("About to give-up screen, flinger = %p", this); - if (hw->isScreenAcquired()) { - if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) { + ALOGD("Screen released, type=%d flinger=%p", hw->getDisplayType(), this); + if (!hw->isScreenAcquired()) { + ALOGD(" screen was previously released"); + return; + } + + hw->releaseScreen(); + int32_t type = hw->getDisplayType(); + if (type < DisplayDevice::NUM_DISPLAY_TYPES) { + if (type == DisplayDevice::DISPLAY_PRIMARY) { // FIXME: eventthread only knows about the main display right now mEventThread->onScreenReleased(); } - hw->releaseScreen(); - getHwComposer().release(); - mVisibleRegionsDirty = true; - // from this point on, SF will stop drawing + + // built-in display, tell the HWC + getHwComposer().release(type); + } + mVisibleRegionsDirty = true; + // from this point on, SF will stop drawing on this display +} + +void SurfaceFlinger::unblank(const sp& display) { + class MessageScreenAcquired : public MessageBase { + SurfaceFlinger* mFlinger; + const sp& mHw; + public: + MessageScreenAcquired(SurfaceFlinger* flinger, + const sp& hw) : mFlinger(flinger), mHw(hw) { } + virtual bool handler() { + mFlinger->onScreenAcquired(mHw); + return true; + } + }; + const sp& hw = getDisplayDevice(display); + if (hw == NULL) { + ALOGE("Attempt to unblank null display %p", display.get()); + } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { + ALOGW("Attempt to unblank virtual display"); + } else { + sp msg = new MessageScreenAcquired(this, hw); + postMessageSync(msg); } } -void SurfaceFlinger::unblank() { - class MessageScreenAcquired : public MessageBase { - SurfaceFlinger* flinger; - public: - MessageScreenAcquired(SurfaceFlinger* flinger) : flinger(flinger) { } - virtual bool handler() { - // FIXME: should this be per-display? - flinger->onScreenAcquired(flinger->getDefaultDisplayDevice()); - return true; - } - }; - sp msg = new MessageScreenAcquired(this); - postMessageSync(msg); -} - -void SurfaceFlinger::blank() { +void SurfaceFlinger::blank(const sp& display) { class MessageScreenReleased : public MessageBase { - SurfaceFlinger* flinger; + SurfaceFlinger* mFlinger; + const sp& mHw; public: - MessageScreenReleased(SurfaceFlinger* flinger) : flinger(flinger) { } + MessageScreenReleased(SurfaceFlinger* flinger, + const sp& hw) : mFlinger(flinger), mHw(hw) { } virtual bool handler() { - // FIXME: should this be per-display? - flinger->onScreenReleased(flinger->getDefaultDisplayDevice()); + mFlinger->onScreenReleased(mHw); return true; } }; - sp msg = new MessageScreenReleased(this); - postMessageSync(msg); + const sp& hw = getDisplayDevice(display); + if (hw == NULL) { + ALOGE("Attempt to blank null display %p", display.get()); + } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { + ALOGW("Attempt to blank virtual display"); + } else { + sp msg = new MessageScreenReleased(this, hw); + postMessageSync(msg); + } } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e5b939d5e..82728484a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -196,9 +196,9 @@ private: uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ); // called when screen needs to turn off - virtual void blank(); + virtual void blank(const sp& display); // called when screen is turning back on - virtual void unblank(); + virtual void unblank(const sp& display); virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info); virtual void connectDisplay(const sp& display);