From 80181b99c7be562b24095ee495712f7197229c74 Mon Sep 17 00:00:00 2001 From: John Reck Date: Tue, 19 May 2015 11:09:32 -0700 Subject: Don't recreate the surface unnecessarily Bug: 19896200 The flicker is caused because ViewRootImpl is requesting a change from OPAQUE to TRANSLUCENT due to the presence of a GLSurfaceView. However, WindowManager will use this as a signal to recreate the SurfaceControl. This is not actually correct, as the underlying format of the SurfaceControl was *already* TRANSLUCENT due to being hardware accelerated. Add a fast-path for this step where the format didn't actually change such that all that is necessary is for the OPAQUE flag to be flushed through to SurfaceFlinger. This doesn't address the larger, more complex issue of a surface flickering if the pixel format really did need to change, but this should address the common case. Change-Id: Ia5275705733123a3d7929bf5951829415753e2b2 --- .../android/server/wm/WindowManagerService.java | 11 +++++---- .../com/android/server/wm/WindowStateAnimator.java | 26 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) (limited to 'services/core/java/com/android/server/wm') diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 3644506..22ef801 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -3209,10 +3209,13 @@ public class WindowManagerService extends IWindowManager.Stub } } if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { - // To change the format, we need to re-build the surface. - winAnimator.destroySurfaceLocked(); - toBeDisplayed = true; - surfaceChanged = true; + // If the format can be changed in place yaay! + // If not, fall back to a surface re-build + if (!winAnimator.tryChangeFormatInPlaceLocked()) { + winAnimator.destroySurfaceLocked(); + toBeDisplayed = true; + surfaceChanged = true; + } } try { if (!win.mHasSurface) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 424e2e2..e9023fd 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -146,6 +146,9 @@ class WindowStateAnimator { boolean mKeyguardGoingAwayAnimation; + /** The pixel format of the underlying SurfaceControl */ + int mSurfaceFormat; + /** This is set when there is no Surface */ static final int NO_SURFACE = 0; /** This is set after the Surface has been created but before the window has been drawn. During @@ -845,6 +848,7 @@ class WindowStateAnimator { flags |= SurfaceControl.OPAQUE; } + mSurfaceFormat = format; if (DEBUG_SURFACE_TRACE) { mSurfaceControl = new SurfaceTrace( mSession.mSurfaceSession, @@ -1610,6 +1614,28 @@ class WindowStateAnimator { } } + /** + * Try to change the pixel format without recreating the surface. This + * will be common in the case of changing from PixelFormat.OPAQUE to + * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both + * requested formats resolve to the same underlying SurfaceControl format + * @return True if format was succesfully changed, false otherwise + */ + boolean tryChangeFormatInPlaceLocked() { + if (mSurfaceControl == null) { + return false; + } + final LayoutParams attrs = mWin.getAttrs(); + final boolean isHwAccelerated = (attrs.flags & + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; + final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format; + if (format == mSurfaceFormat) { + setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format)); + return true; + } + return false; + } + void setOpaqueLocked(boolean isOpaque) { if (mSurfaceControl == null) { return; -- cgit v1.1