Add support for pausing/resuming composition from Java.
authorAli Juma <ajuma@mozilla.com>
Sun, 05 Feb 2012 13:33:38 -0500
changeset 92387 d721b3df0c6bdd8e0ea83ec816b94453d13ca49b
parent 92386 d678113069ca2b8d5b9e96596576cc4526d6a049
child 92388 43016f417f0bc2a1d22c4078ecbc2eb9eb02af00
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.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
Add support for pausing/resuming composition from Java.
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
mobile/android/base/GeckoAppShell.java
mobile/android/base/gfx/FlexibleGLSurfaceView.java
mobile/android/base/gfx/GeckoGLLayerClient.java
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJNI.cpp
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -47,17 +47,17 @@
 #include "AndroidBridge.h"
 #include <android/log.h>
 #endif
 
 namespace mozilla {
 namespace layers {
 
 CompositorParent::CompositorParent(nsIWidget* aWidget)
-  : mStopped(false), mWidget(aWidget)
+  : mPaused(false), mWidget(aWidget)
 {
   MOZ_COUNT_CTOR(CompositorParent);
 }
 
 CompositorParent::~CompositorParent()
 {
   MOZ_COUNT_DTOR(CompositorParent);
 }
@@ -70,30 +70,66 @@ CompositorParent::Destroy()
 
   // Ensure that the layer manager is destroyed on the compositor thread.
   mLayerManager = NULL;
 }
 
 bool
 CompositorParent::RecvStop()
 {
-  mStopped = true;
+  mPaused = true;
   Destroy();
   return true;
 }
 
 
 void
 CompositorParent::ScheduleRenderOnCompositorThread(::base::Thread &aCompositorThread)
 {
   CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::AsyncRender);
   aCompositorThread.message_loop()->PostTask(FROM_HERE, renderTask);
 }
 
 void
+CompositorParent::PauseComposition()
+{
+  mPaused = true;
+
+#ifdef MOZ_WIDGET_ANDROID
+  // TODO: Tell GLContextEGL we're paused, so it should release surface.
+#endif
+}
+
+void
+CompositorParent::ResumeComposition()
+{
+  mPaused = false;
+
+#ifdef MOZ_WIDGET_ANDROID
+  // TODO: Tell GLContextEGL we've resumed, so it should obtain new surface.
+#endif
+}
+
+void
+CompositorParent::SchedulePauseOnCompositorThread(::base::Thread &aCompositorThread)
+{
+  CancelableTask *pauseTask = NewRunnableMethod(this,
+                                                &CompositorParent::PauseComposition);
+  aCompositorThread.message_loop()->PostTask(FROM_HERE, pauseTask);
+}
+
+void
+CompositorParent::ScheduleResumeOnCompositorThread(::base::Thread &aCompositorThread)
+{
+  CancelableTask *resumeTask = NewRunnableMethod(this,
+                                                 &CompositorParent::ResumeComposition);
+  aCompositorThread.message_loop()->PostTask(FROM_HERE, resumeTask);
+}
+
+void
 CompositorParent::ScheduleComposition()
 {
   printf_stderr("Schedule composition\n");
   CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite);
   MessageLoop::current()->PostTask(FROM_HERE, composeTask);
 
 // Test code for async scrolling.
 #ifdef OMTC_TEST_ASYNC_SCROLLING
@@ -113,17 +149,17 @@ CompositorParent::SetTransformation(floa
   mXScale = aScale;
   mYScale = aScale;
   mScrollOffset = aScrollOffset;
 }
 
 void
 CompositorParent::Composite()
 {
-  if (mStopped || !mLayerManager) {
+  if (mPaused || !mLayerManager) {
     return;
   }
 
   mLayerManager->EndEmptyTransaction();
 }
 
 // Go down shadow layer tree, setting properties to match their non-shadow
 // counterparts.
@@ -213,17 +249,17 @@ CompositorParent::TransformShadowTree(La
                        aTempScaleDiffY);
   }*/
 
 }
 
 void
 CompositorParent::AsyncRender()
 {
-  if (mStopped || !mLayerManager) {
+  if (mPaused || !mLayerManager) {
     return;
   }
 
   Layer* root = mLayerManager->GetRoot();
 
 /*
   ContainerLayer* container = root->AsContainerLayer();
   if (!container)
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -87,16 +87,21 @@ public:
   void Destroy();
 
   LayerManager* GetLayerManager() { return mLayerManager; }
 
   void SetTransformation(float aScale, nsIntPoint aScrollOffset);
   void AsyncRender();
   void ScheduleRenderOnCompositorThread(::base::Thread &aCompositorThread);
 
+  void PauseComposition();
+  void ResumeComposition();
+  void SchedulePauseOnCompositorThread(::base::Thread &aCompositorThread);
+  void ScheduleResumeOnCompositorThread(::base::Thread &aCompositorThread);
+
 protected:
   virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
   virtual bool DeallocPLayers(PLayersParent* aLayers);
 
 private:
   void ScheduleComposition();
   void Composite();
 #ifdef OMTC_TEST_ASYNC_SCROLLING
@@ -118,17 +123,17 @@ private:
   /**
    * Asks Java for the viewport position and updates the world transform
    * accordingly.
    */
   void RequestViewTransform();
 #endif
 
   nsRefPtr<LayerManager> mLayerManager;
-  bool mStopped;
+  bool mPaused;
   nsIWidget* mWidget;
   float mXScale;
   float mYScale;
   nsIntPoint mScrollOffset;
 
   DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
 };
 
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -166,16 +166,18 @@ public class GeckoAppShell
     public static native void notifyListCreated(int aListId, int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyGotNextMessage(int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyReadingMessageListFailed(int aError, int aRequestId, long aProcessId);
 
     public static native ByteBuffer allocateDirectBuffer(long size);
     public static native void freeDirectBuffer(ByteBuffer buf);
     public static native void bindWidgetTexture();
     public static native void scheduleComposite();
+    public static native void schedulePauseComposition();
+    public static native void scheduleResumeComposition();
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
             setName("GeckoLooper Thread");
--- a/mobile/android/base/gfx/FlexibleGLSurfaceView.java
+++ b/mobile/android/base/gfx/FlexibleGLSurfaceView.java
@@ -187,16 +187,18 @@ public class FlexibleGLSurfaceView exten
         } catch (Exception e) {
             Log.e(LOGTAG, "### Exception! " + e);
             return null;
         }
     }
 
     public interface Listener {
         void renderRequested();
+        void compositionPauseRequested();
+        void compositionResumeRequested();
     }
 
     public static class FlexibleGLSurfaceViewException extends RuntimeException {
         public static final long serialVersionUID = 1L;
 
         FlexibleGLSurfaceViewException(String e) {
             super(e);
         }
--- a/mobile/android/base/gfx/GeckoGLLayerClient.java
+++ b/mobile/android/base/gfx/GeckoGLLayerClient.java
@@ -188,10 +188,20 @@ public class GeckoGLLayerClient extends 
             return new ViewTransform(scrollX, scrollY, zoomFactor);
         }
     }
 
     public void renderRequested() {
         Log.e(LOGTAG, "### Render requested, scheduling composite");
         GeckoAppShell.scheduleComposite();
     }
+
+    public void compositionPauseRequested() {
+        Log.e(LOGTAG, "### Scheduling PauseComposition");
+        GeckoAppShell.schedulePauseComposition();
+    }
+
+    public void compositionResumeRequested() {
+        Log.e(LOGTAG, "### Scheduling ResumeComposition");
+        GeckoAppShell.scheduleResumeComposition();
+    }
 }
 
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -1865,16 +1865,32 @@ void
 AndroidBridge::ScheduleComposite()
 {
     if (mCompositorParent) {
         mCompositorParent->ScheduleRenderOnCompositorThread(*mCompositorThread);
     }
 }
 
 void
+AndroidBridge::SchedulePauseComposition()
+{
+    if (mCompositorParent) {
+        mCompositorParent->SchedulePauseOnCompositorThread(*mCompositorThread);
+    }
+}
+
+void
+AndroidBridge::ScheduleResumeComposition()
+{
+    if (mCompositorParent) {
+        mCompositorParent->ScheduleResumeOnCompositorThread(*mCompositorThread);
+    }
+}
+
+void
 AndroidBridge::SetViewTransformGetter(AndroidViewTransformGetter& aViewTransformGetter)
 {
     __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### SetViewTransformGetter()");
     mViewTransformGetter = &aViewTransformGetter;
 }
 
 void
 AndroidBridge::GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY)
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -398,16 +398,18 @@ public:
 
     void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
     void EnableNetworkNotifications();
     void DisableNetworkNotifications();
 
     void SetCompositorParent(mozilla::layers::CompositorParent* aCompositorParent,
                              base::Thread* aCompositorThread);
     void ScheduleComposite();
+    void SchedulePauseComposition();
+    void ScheduleResumeComposition();
     void SetViewTransformGetter(AndroidViewTransformGetter& aViewTransformGetter);
     void GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
 
 protected:
     static AndroidBridge *sBridge;
 
     // the global JavaVM
     JavaVM *mJavaVM;
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -102,16 +102,18 @@ extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyNoMessageInList(JNIEnv* jenv, jclass, jint, jlong);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyListCreated(JNIEnv* jenv, jclass, jint, jint, jstring, jstring, jstring, jlong, jint, jlong);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGotNextMessage(JNIEnv* jenv, jclass, jint, jstring, jstring, jstring, jlong, jint, jlong);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyReadingMessageListFailed(JNIEnv* jenv, jclass, jint, jint, jlong);
 
 #ifdef MOZ_JAVA_COMPOSITOR
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv* jenv, jclass);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_schedulePauseComposition(JNIEnv* jenv, jclass);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv* jenv, jclass);
 #endif
 
 }
 
 
 /*
  * Incoming JNI methods
  */
@@ -856,9 +858,23 @@ Java_org_mozilla_gecko_GeckoAppShell_bin
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*, jclass)
 {
     __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### scheduleComposite()");
     AndroidBridge::Bridge()->ScheduleComposite();
 }
 
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_schedulePauseComposition(JNIEnv*, jclass)
+{
+    __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### schedulePauseComposition()");
+    AndroidBridge::Bridge()->SchedulePauseComposition();
+}
+
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*, jclass)
+{
+    __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### scheduleResumeComposition()");
+    AndroidBridge::Bridge()->ScheduleResumeComposition();
+}
+
 #endif