diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 2b79a76bde45a..d5cad9634106d 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -201,6 +201,14 @@ class GLES20Canvas extends HardwareCanvas { private static native void nSetViewport(int renderer, int width, int height); /** + * Preserves the back buffer of the current surface after a buffer swap. + * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current + * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL + * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT. + * + * @return True if the swap behavior was successfully changed, + * false otherwise. + * * @hide */ public static boolean preserveBackBuffer() { @@ -208,6 +216,21 @@ class GLES20Canvas extends HardwareCanvas { } private static native boolean nPreserveBackBuffer(); + + /** + * Indicates whether the current surface preserves its back buffer + * after a buffer swap. + * + * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED, + * false otherwise + * + * @hide + */ + public static boolean isBackBufferPreserved() { + return nIsBackBufferPreserved(); + } + + private static native boolean nIsBackBufferPreserved(); @Override void onPreDraw(Rect dirty) { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 61a24a0fb950a..2611ec0752c22 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -311,6 +311,7 @@ public abstract class HardwareRenderer { Paint mDebugPaint; boolean mDirtyRegions; + final boolean mDirtyRegionsRequested; final int mGlVersion; final boolean mTranslucent; @@ -325,6 +326,7 @@ public abstract class HardwareRenderer { final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true"); //noinspection PointlessBooleanExpression,ConstantConditions mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); + mDirtyRegionsRequested = mDirtyRegions; } /** @@ -545,11 +547,21 @@ public abstract class HardwareRenderer { throw new Surface.OutOfResourcesException("eglMakeCurrent failed " + getEGLErrorString(sEgl.eglGetError())); } - + + // If mDirtyRegions is set, this means we have an EGL configuration + // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set if (mDirtyRegions) { if (!GLES20Canvas.preserveBackBuffer()) { Log.w(LOG_TAG, "Backbuffer cannot be preserved"); } + } else if (mDirtyRegionsRequested) { + // If mDirtyRegions is not set, our EGL configuration does not + // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default + // swap behavior might be EGL_BUFFER_PRESERVED, which means we + // want to set mDirtyRegions. We try to do this only if dirty + // regions were initially requested as part of the device + // configuration (see RENDER_DIRTY_REGIONS) + mDirtyRegions = GLES20Canvas.isBackBufferPreserved(); } return sEglContext.getGL(); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index e2832ed774f2c..31988f710276c 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -91,11 +91,29 @@ static jboolean android_view_GLES20Canvas_preserveBackBuffer(JNIEnv* env, jobjec eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); EGLint error = eglGetError(); - RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error); + if (error != EGL_SUCCESS) { + RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error); + } return error == EGL_SUCCESS; } +static jboolean android_view_GLES20Canvas_isBackBufferPreserved(JNIEnv* env, jobject clazz) { + EGLDisplay display = eglGetCurrentDisplay(); + EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); + EGLint value; + + eglGetError(); + eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value); + + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) { + RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error); + } + + return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED; +} + // ---------------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------------- @@ -676,7 +694,8 @@ static JNINativeMethod gMethods[] = { { "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable }, #ifdef USE_OPENGL_RENDERER - { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, + { "nIsBackBufferPreserved", "()Z", (void*) android_view_GLES20Canvas_isBackBufferPreserved }, + { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },