From 02d86567d95b99e1142941ed7ec23a4465822813 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Mon, 25 Mar 2013 14:43:23 -0700 Subject: [PATCH] Clean up HWC state when releasing a DisplayDevice DisplayDevices can be released when DisplayManager removes them from the display list, or (for virtual displays) when the surface is set to NULL. We were only cleaning up HWC resources associated with the display in the first case. Bug: 8384764 Change-Id: Id3d226dd7178fbe6d0a2ac4e2660b864ee073de3 --- services/surfaceflinger/DisplayDevice.cpp | 13 ++++++++++-- services/surfaceflinger/DisplayDevice.h | 3 +++ .../DisplayHardware/HWComposer.cpp | 12 +++++------ services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++++++++------ services/surfaceflinger/SurfaceFlinger.h | 6 +++--- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 6936a7f86..68b0b7f15 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -143,6 +143,15 @@ DisplayDevice::~DisplayDevice() { } } +void DisplayDevice::disconnect(HWComposer& hwc) { + if (mHwcDisplayId >= 0) { + hwc.disconnectDisplay(mHwcDisplayId); + if (mHwcDisplayId >= DISPLAY_VIRTUAL) + hwc.freeDisplayId(mHwcDisplayId); + mHwcDisplayId = -1; + } +} + bool DisplayDevice::isValid() const { return mFlinger != NULL; } @@ -419,11 +428,11 @@ void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const { const Transform& tr(mGlobalTransform); snprintf(buffer, SIZE, "+ DisplayDevice: %s\n" - " type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " + " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n" " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", - mDisplayName.string(), mType, + mDisplayName.string(), mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), mOrientation, tr.getType(), getPageFlipCount(), mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d4a6daaeb..377d924ef 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -146,6 +146,9 @@ public: bool isScreenAcquired() const; bool canDraw() const; + // release HWC resources (if any) for removable displays + void disconnect(HWComposer& hwc); + /* ------------------------------------------------------------------------ * Debugging */ diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 497593bba..86e674ac7 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -953,17 +953,17 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync); for (size_t i=0 ; i >& visibleLayersSortedByZ = mFlinger->getLayerSortedByZForHwcDisplay(i); - if (disp.connected) { - result.appendFormat( - " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", - i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - } + result.appendFormat( + " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", + i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - if (disp.list && disp.connected) { + if (disp.list) { result.appendFormat( " numHwLayers=%u, flags=%08x\n", disp.list->numHwLayers, disp.list->flags); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a210f7ac..ed6574a01 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1102,12 +1102,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. - const sp hw(getDefaultDisplayDevice()); - DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext); - mDisplays.removeItem(draw.keyAt(i)); - getHwComposer().disconnectDisplay(draw[i].type); + const sp defaultDisplay(getDefaultDisplayDevice()); + DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext); + sp hw(getDisplayDevice(draw.keyAt(i))); + if (hw != NULL) + hw->disconnect(getHwComposer()); if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES) mEventThread->onHotplugReceived(draw[i].type, false); + mDisplays.removeItem(draw.keyAt(i)); } else { ALOGW("trying to remove the main display"); } @@ -1120,6 +1122,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. + sp hw(getDisplayDevice(display)); + if (hw != NULL) + hw->disconnect(getHwComposer()); mDisplays.removeItem(display); mDrawingState.displays.removeItemsAt(i); dc--; i--; @@ -1150,9 +1155,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const DisplayDeviceState& state(curr[i]); sp dispSurface; - int32_t hwcDisplayId = allocateHwcDisplayId(state.type); + int32_t hwcDisplayId = -1; if (state.isVirtualDisplay()) { + // Virtual displays without a surface are dormant: + // they have external state (layer stack, projection, + // etc.) but no internal state (i.e. a DisplayDevice). if (state.surface != NULL) { + hwcDisplayId = allocateHwcDisplayId(state.type); dispSurface = new VirtualDisplaySurface( *mHwc, hwcDisplayId, state.surface, state.displayName); @@ -1162,7 +1171,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); - + hwcDisplayId = allocateHwcDisplayId(state.type); // for supported (by hwc) displays we provide our // own rendering surface dispSurface = new FramebufferSurface(*mHwc, state.type); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f0e6deb1a..57ee8b92e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -108,9 +108,6 @@ public: // utility function to delete a texture on the main thread void deleteTextureAsync(GLuint texture); - // allocate a h/w composer display id - int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type); - // enable/disable h/w composer event // TODO: this should be made accessible only to EventThread void eventControl(int disp, int event, int enabled); @@ -338,6 +335,9 @@ private: // region of all screens presenting this layer stack. void invalidateLayerStack(uint32_t layerStack, const Region& dirty); + // allocate a h/w composer display id + int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type); + /* ------------------------------------------------------------------------ * H/W composer */