diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp index 34d64afb6e25..f7d21a8dde10 100644 --- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -520,7 +520,10 @@ public: EGL_NO_CONTEXT); if (!mSurface) { #ifdef MOZ_ANDROID_OMTC - mSurface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface(); + mSurface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface(false); + if (!mSurface) { + return false; + } #else EGLConfig config; CreateConfig(&config); @@ -2191,7 +2194,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget) #ifdef MOZ_ANDROID_OMTC mozilla::AndroidBridge::Bridge()->RegisterCompositor(); - EGLSurface surface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface(); + EGLSurface surface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface(true); #else EGLSurface surface = CreateSurfaceForWindow(aWidget, config); #endif diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 5a98ba3d079d..a788bcabc182 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -346,12 +346,17 @@ CompositorParent::ResumeComposition() MonitorAutoLock lock(mResumeCompositionMonitor); - mPaused = false; - #ifdef MOZ_WIDGET_ANDROID - static_cast(mLayerManager.get())->gl()->RenewSurface(); + if (!static_cast(mLayerManager.get())->gl()->RenewSurface()) { + // We can't get a surface. This could be because the activity changed between + // the time resume was scheduled and now. + __android_log_print(ANDROID_LOG_INFO, "CompositorParent", "Unable to renew compositor surface; remaining in paused state"); + lock.NotifyAll(); + return; + } #endif + mPaused = false; Composite(); // if anyone's waiting to make sure that composition really got resumed, tell them @@ -402,7 +407,7 @@ CompositorParent::SchedulePauseOnCompositorThread() lock.Wait(); } -void +bool CompositorParent::ScheduleResumeOnCompositorThread(int width, int height) { MonitorAutoLock lock(mResumeCompositionMonitor); @@ -413,6 +418,8 @@ CompositorParent::ScheduleResumeOnCompositorThread(int width, int height) // Wait until the resume has actually been processed by the compositor thread lock.Wait(); + + return !mPaused; } void diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 3512b4470911..d6817f23e4c4 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -85,7 +85,11 @@ public: // Can be called from any thread void ScheduleRenderOnCompositorThread(); void SchedulePauseOnCompositorThread(); - void ScheduleResumeOnCompositorThread(int width, int height); + /** + * Returns true if a surface was obtained and the resume succeeded; false + * otherwise. + */ + bool ScheduleResumeOnCompositorThread(int width, int height); virtual void ScheduleComposition(); void NotifyShadowTreeTransaction(); diff --git a/mobile/android/base/gfx/GLController.java b/mobile/android/base/gfx/GLController.java index 86c191903d24..65cd8625451c 100644 --- a/mobile/android/base/gfx/GLController.java +++ b/mobile/android/base/gfx/GLController.java @@ -127,6 +127,12 @@ public class GLController { * caller assumes ownership of the surface once it is returned. * This function is invoked by JNI */ private EGLSurface provideEGLSurface() { + synchronized (this) { + if (!mSurfaceValid) { + return null; + } + } + if (mEGL == null) { initEGL(); } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 6944d0b64f80..6c477c47b502 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -1205,9 +1205,11 @@ AndroidBridge::RegisterCompositor(JNIEnv *env, bool resetting) } EGLSurface -AndroidBridge::ProvideEGLSurface() +AndroidBridge::ProvideEGLSurface(bool waitUntilValid) { - sController.WaitForValidSurface(); + if (waitUntilValid) { + sController.WaitForValidSurface(); + } return sController.ProvideEGLSurface(); } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index ec801f1271de..daa12b820510 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -261,7 +261,7 @@ public: // Switch Java to composite with the Gecko Compositor thread void RegisterCompositor(JNIEnv* env = NULL, bool resetting = false); - EGLSurface ProvideEGLSurface(); + EGLSurface ProvideEGLSurface(bool waitUntilValid); bool GetStaticStringField(const char *classID, const char *field, nsAString &result, JNIEnv* env = nullptr); diff --git a/widget/android/AndroidLayerViewWrapper.cpp b/widget/android/AndroidLayerViewWrapper.cpp index 08157619c15c..c8cb11d0b1e1 100644 --- a/widget/android/AndroidLayerViewWrapper.cpp +++ b/widget/android/AndroidLayerViewWrapper.cpp @@ -60,7 +60,7 @@ AndroidGLController::ProvideEGLSurface() ASSERT_THREAD(); AutoLocalJNIFrame jniFrame(mJEnv); jobject jObj = mJEnv->CallObjectMethod(mJObj, jProvideEGLSurfaceMethod); - if (jniFrame.CheckForException()) + if (jniFrame.CheckForException() || !jObj) return NULL; return reinterpret_cast(mJEnv->GetIntField(jObj, jEGLSurfacePointerField)); diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 8327573d0069..f990e06f8c46 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -940,8 +940,9 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae) // Since we might have prevented one or more draw events from // occurring while the compositor was paused, we need to schedule // a draw event now. - sCompositorPaused = false; - win->RedrawAll(); + if (!sCompositorPaused) { + win->RedrawAll(); + } break; case AndroidGeckoEvent::GECKO_EVENT_SYNC: @@ -2312,8 +2313,8 @@ nsWindow::SchedulePauseComposition() void nsWindow::ScheduleResumeComposition(int width, int height) { - if (sCompositorParent) { - sCompositorParent->ScheduleResumeOnCompositorThread(width, height); + if (sCompositorParent && sCompositorParent->ScheduleResumeOnCompositorThread(width, height)) { + sCompositorPaused = false; } }