From d10cd5765a2b706fc174f16b951d6b0a5d3740d3 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Sun, 10 Oct 2010 13:33:22 -0700 Subject: [PATCH] Always create OpenGL accelerated windows in RGBA 8888. Bug #3081600 The OpenGL renderer in libhwui uses a single EGL context per process and thus create it with an RGBA 8888 EGL configuration. To ensure that all windows are compatible with this configuration, this change modifies the window manager and SurfaceFlinger. The window manager now checks the window's flags and if the window is hardware accelerated, it forces the window's pixel format to be translucent when creating the surface. The window itself is still marked as opaque if we know that the window will be opaque on screen. This keeps existing optimizations in place. Similarly in SurfaceFlinger, a translucent Surface can now be created with the Surface.OPAQUE flag, indicating SurfaceFlinger that the surface does not require blending, despite its RGBA 8888 configuration. Change-Id: Ic747b6b12564ba064412d842117880fcc199eb7c --- core/java/android/view/HardwareRenderer.java | 12 +++---- core/java/android/view/Surface.java | 31 +++++++++++++------ include/surfaceflinger/ISurfaceComposer.h | 1 + .../android/server/WindowManagerService.java | 8 ++++- services/surfaceflinger/Layer.cpp | 3 +- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 69bdef05e601b..0247f6a7828a5 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -216,9 +216,11 @@ public abstract class HardwareRenderer { /** * Return a string for the EGL error code, or the hex representation - * if an unknown error. - * @param error EGL error. - * @return Error string. + * if the error is unknown. + * + * @param error The EGL error to convert into a String. + * + * @return An error string correponding to the EGL error code. */ static String getEGLErrorString(int error) { switch (error) { @@ -446,11 +448,9 @@ public abstract class HardwareRenderer { } /** - * Defines the EGL configuration for this renderer. The default configuration - * is RGBX, no depth, no stencil. + * Defines the EGL configuration for this renderer. * * @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}. - * @param glVersion */ EglConfigChooser getConfigChooser(int glVersion) { return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0); diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index cd0ae3b02fbb3..d596a7f9bb189 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -86,6 +86,15 @@ public class Surface implements Parcelable { * play back. */ public static final int PUSH_BUFFERS = 0x00000200; + /** + * Indicates that the surface must be considered opaque, even if its + * pixel format is set to translucent. This can be useful if an + * application needs full RGBA 8888 support for instance but will + * still draw every pixel opaque. + * + * @hide + */ + public static final int OPAQUE = 0x00000400; /** Creates a normal surface. This is the default */ public static final int FX_SURFACE_NORMAL = 0x00000000; @@ -269,7 +278,7 @@ public class Surface implements Parcelable { } mOrigMatrix.set(m); } - }; + } /** * Sets the display metrics used to provide canva's width/height in compatibility mode. @@ -422,16 +431,20 @@ public class Surface implements Parcelable { /* no user serviceable parts here ... */ @Override protected void finalize() throws Throwable { - if (mNativeSurface != 0 || mSurfaceControl != 0) { - if (DEBUG_RELEASE) { - Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" - + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack); - } else { - Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" - + mNativeSurface + ", " + mSurfaceControl + ")"); + try { + super.finalize(); + } finally { + if (mNativeSurface != 0 || mSurfaceControl != 0) { + if (DEBUG_RELEASE) { + Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" + + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack); + } else { + Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" + + mNativeSurface + ", " + mSurfaceControl + ")"); + } } + release(); } - release(); } private native void init(SurfaceSession s, diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h index 6533600238596..b18178128fa4d 100644 --- a/include/surfaceflinger/ISurfaceComposer.h +++ b/include/surfaceflinger/ISurfaceComposer.h @@ -43,6 +43,7 @@ public: eSecure = 0x00000080, eNonPremultiplied = 0x00000100, ePushBuffers = 0x00000200, + eOpaque = 0x00000400, eFXSurfaceNormal = 0x00000000, eFXSurfaceBlur = 0x00010000, diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 8be980fe2cc64..92c5cc8b1b744 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -6832,10 +6832,16 @@ public class WindowManagerService extends IWindowManager.Stub mSurfaceW = w; mSurfaceH = h; try { + final boolean isHwAccelerated = (mAttrs.flags & + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0; + final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format; + if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) { + flags |= Surface.OPAQUE; + } mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), - 0, w, h, mAttrs.format, flags); + 0, w, h, format, flags); if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE " + mSurface + " IN SESSION " + mSession.mSurfaceSession diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fb76720084c6b..1b06843df7eef 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -171,7 +171,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mReqHeight = h; mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; - mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; + mNeedsBlending = (info.h_alpha - info.l_alpha) > 0 && + (flags & ISurfaceComposer::eOpaque) == 0; // we use the red index int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);