Bug 677920 - Part 2: Fix handling of Android surface lifecycle events when using GL layers. r=blassey
authorAli Juma <ajuma@mozilla.com>
Tue, 23 Aug 2011 16:52:03 -0400
changeset 75776 6f12501fde073115b7babd7d78be9636a3401f06
parent 75775 6e7449c449ba336e49e2167d8edf3c28169c9962
child 75777 5afcb349cb1cda0c930b94a8f47c5a652d931647
push id21056
push usermak77@bonardo.net
push dateWed, 24 Aug 2011 08:19:04 +0000
treeherdermozilla-central@5d9989c3bff6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs677920
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 677920 - Part 2: Fix handling of Android surface lifecycle events when using GL layers. r=blassey
embedding/android/GeckoSurfaceView.java
widget/src/android/nsAppShell.cpp
widget/src/android/nsWindow.cpp
--- a/embedding/android/GeckoSurfaceView.java
+++ b/embedding/android/GeckoSurfaceView.java
@@ -277,17 +277,22 @@ class GeckoSurfaceView
 
     public void surfaceDestroyed(SurfaceHolder holder) {
         Log.i(LOG_FILE_NAME, "surface destroyed");
         mSurfaceValid = false;
         mSoftwareBuffer = null;
         mSoftwareBufferCopy = null;
         mSoftwareBitmap = null;
         GeckoEvent e = new GeckoEvent(GeckoEvent.SURFACE_DESTROYED);
-        GeckoAppShell.sendEventToGecko(e);
+        if (mDrawMode == DRAW_GLES_2) {
+            // Ensure GL cleanup occurs before we return.
+            GeckoAppShell.sendEventToGeckoSync(e);
+        } else {
+            GeckoAppShell.sendEventToGecko(e);
+        }
     }
 
     public Bitmap getSoftwareDrawBitmap() {
         if (mSoftwareBitmap == null ||
             mSoftwareBitmap.getHeight() != mHeight ||
             mSoftwareBitmap.getWidth() != mWidth) {
             mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
         }
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -441,19 +441,38 @@ nsAppShell::PeekNextEvent()
     }
 
     return ae;
 }
 
 void
 nsAppShell::PostEvent(AndroidGeckoEvent *ae)
 {
+    if (ae->Type() == AndroidGeckoEvent::ACTIVITY_STOPPING) {
+        PostEvent(new AndroidGeckoEvent(AndroidGeckoEvent::SURFACE_DESTROYED));
+    }
+
     {
         MutexAutoLock lock(mQueueLock);
-        mEventQueue.AppendElement(ae);
+        if (ae->Type() == AndroidGeckoEvent::SURFACE_DESTROYED) {
+            // Give priority to this event, and discard any pending
+            // SURFACE_CREATED events.
+            mEventQueue.InsertElementAt(0, ae);
+            AndroidGeckoEvent *event;
+            for (int i = mEventQueue.Length()-1; i >=1; i--) {
+                event = mEventQueue[i];
+                if (event->Type() == AndroidGeckoEvent::SURFACE_CREATED) {
+                    mEventQueue.RemoveElementAt(i);
+                    delete event;
+                }
+            }
+        } else {
+            mEventQueue.AppendElement(ae);
+        }
+
         if (ae->Type() == AndroidGeckoEvent::DRAW) {
             mNumDraws++;
         }
     }
     NotifyNativeEvent();
 }
 
 void
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -123,16 +123,17 @@ static PRBool gMenuConsumed;
 // All the toplevel windows that have been created; these are in
 // stacking order, so the window at gAndroidBounds[0] is the topmost
 // one.
 static nsTArray<nsWindow*> gTopLevelWindows;
 
 static nsRefPtr<gl::GLContext> sGLContext;
 static bool sFailedToCreateGLContext = false;
 static bool sValidSurface;
+static bool sSurfaceExists = false;
 
 // Multitouch swipe thresholds in inches
 static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4;
 static const double SWIPE_MIN_DISTANCE_INCHES = 0.6;
 
 static nsWindow*
 TopWindow()
 {
@@ -839,19 +840,24 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
                 win->mFocus->OnIMEEvent(ae);
             } else {
                 NS_WARNING("Sending unexpected IME event to top window");
                 win->OnIMEEvent(ae);
             }
             break;
 
         case AndroidGeckoEvent::SURFACE_CREATED:
+            sSurfaceExists = true;
             break;
 
         case AndroidGeckoEvent::SURFACE_DESTROYED:
+            if (sGLContext && sValidSurface) {
+                sGLContext->ReleaseSurface();
+            }
+            sSurfaceExists = false;
             sValidSurface = false;
             break;
 
         case AndroidGeckoEvent::GECKO_EVENT_SYNC:
             AndroidBridge::Bridge()->AcknowledgeEventSync();
             break;
 
         default:
@@ -965,16 +971,21 @@ nsWindow::DrawTo(gfxASurface *targetSurf
         targetSurface->SetDeviceOffset(offset);
 
     return PR_TRUE;
 }
 
 void
 nsWindow::OnDraw(AndroidGeckoEvent *ae)
 {
+  
+    if (!sSurfaceExists) {
+        return;
+    }
+
     if (!IsTopLevel()) {
         ALOG("##### redraw for window %p, which is not a toplevel window -- sending to toplevel!", (void*) this);
         DumpWindows();
         return;
     }
 
     if (!mIsVisible) {
         ALOG("##### redraw for window %p, which is not visible -- ignoring!", (void*) this);