OSDN Git Service

Detect surface resizes
authorRomain Guy <romainguy@google.com>
Fri, 30 Mar 2012 21:54:22 +0000 (14:54 -0700)
committerRomain Guy <romainguy@google.com>
Fri, 30 Mar 2012 21:54:22 +0000 (14:54 -0700)
HardwareRenderer normally relies on the window manager to be notified of
surface dimension changes. It is however possible to execute a drawing pass
before receiving the window manager notification. We must therefore compare
the actual size of the target surface to the window size and perform a full
redraw when they are not the same.

Change-Id: Idccc8592f3f777edee1ef67a98a4c2a825dcfba7

core/java/android/view/HardwareRenderer.java
core/jni/android_view_HardwareRenderer.cpp

index 81c7ebf..be640dc 100644 (file)
@@ -274,12 +274,13 @@ public abstract class HardwareRenderer {
 
     /**
      * Notifies EGL that the frame is about to be rendered.
+     * @param size
      */
-    private static void beginFrame() {
-        nBeginFrame();
+    private static void beginFrame(int[] size) {
+        nBeginFrame(size);
     }
 
-    private static native void nBeginFrame();
+    private static native void nBeginFrame(int[] size);
 
     /**
      * Preserves the back buffer of the current surface after a buffer swap.
@@ -541,6 +542,7 @@ public abstract class HardwareRenderer {
         private boolean mDestroyed;
 
         private final Rect mRedrawClip = new Rect();
+        private final int[] mSurfaceSize = new int[2];
 
         GlRenderer(int glVersion, boolean translucent) {
             mGlVersion = glVersion;
@@ -957,17 +959,29 @@ public abstract class HardwareRenderer {
 
                 final int surfaceState = checkCurrent();
                 if (surfaceState != SURFACE_STATE_ERROR) {
+                    HardwareCanvas canvas = mCanvas;
+                    attachInfo.mHardwareCanvas = canvas;
+                    
                     // We had to change the current surface and/or context, redraw everything
                     if (surfaceState == SURFACE_STATE_UPDATED) {
                         dirty = null;
+                        beginFrame(null);
+                    } else {
+                        int[] size = mSurfaceSize;
+                        beginFrame(size);
+
+                        if (size[1] != mHeight || size[0] != mWidth) {
+                            mWidth = size[0];
+                            mHeight = size[1];
+
+                            canvas.setViewport(mWidth, mHeight);
+
+                            dirty = null;
+                        }
                     }
 
-                    beginFrame();
                     onPreDraw(dirty);
 
-                    HardwareCanvas canvas = mCanvas;
-                    attachInfo.mHardwareCanvas = canvas;
-
                     int saveCount = canvas.save();
                     callbacks.onHardwarePreDraw(canvas);
 
index 4b62169..082e726 100644 (file)
@@ -99,10 +99,26 @@ static void android_view_HardwareRenderer_disableVsync(JNIEnv* env, jobject claz
 // Tracing and debugging
 // ----------------------------------------------------------------------------
 
-static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz) {
-    EGLDisplay dpy = eglGetCurrentDisplay();
-    EGLSurface surf = eglGetCurrentSurface(EGL_DRAW);
-    eglBeginFrame(dpy, surf);
+static void android_view_HardwareRenderer_beginFrame(JNIEnv* env, jobject clazz,
+        jintArray size) {
+
+    EGLDisplay display = eglGetCurrentDisplay();
+    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
+
+    if (size) {
+        EGLint value;
+        jint* storage = env->GetIntArrayElements(size, NULL);
+
+        eglQuerySurface(display, surface, EGL_WIDTH, &value);
+        storage[0] = value;
+
+        eglQuerySurface(display, surface, EGL_HEIGHT, &value);
+        storage[1] = value;
+
+        env->ReleaseIntArrayElements(size, storage, 0);
+    }
+
+    eglBeginFrame(display, surface);
 }
 
 #endif // USE_OPENGL_RENDERER
@@ -127,15 +143,11 @@ const char* const kClassPathName = "android/view/HardwareRenderer";
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
-    { "nIsBackBufferPreserved", "()Z",
-            (void*) android_view_HardwareRenderer_isBackBufferPreserved },
-    { "nPreserveBackBuffer",    "()Z",
-            (void*) android_view_HardwareRenderer_preserveBackBuffer },
-    { "nDisableVsync",          "()V",
-            (void*) android_view_HardwareRenderer_disableVsync },
-
-    { "nBeginFrame", "()V",
-            (void*) android_view_HardwareRenderer_beginFrame },
+    { "nIsBackBufferPreserved", "()Z",   (void*) android_view_HardwareRenderer_isBackBufferPreserved },
+    { "nPreserveBackBuffer",    "()Z",   (void*) android_view_HardwareRenderer_preserveBackBuffer },
+    { "nDisableVsync",          "()V",   (void*) android_view_HardwareRenderer_disableVsync },
+
+    { "nBeginFrame",            "([I)V", (void*) android_view_HardwareRenderer_beginFrame },
 #endif
 
     { "nSetupShadersDiskCache", "(Ljava/lang/String;)V",