Bug 725095 - Address review comments in the widget code. r=blassey
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 14 Mar 2012 00:15:11 -0400
changeset 89353 8e11e5b9c9351ae8e82fb3f83ef611efd734a02c
parent 89352 799af2f4aaf25c5c899195dbc41fbb185f89f5a0
child 89354 177a960d55959d6244cfb65fc650b6455dc5c455
push id22242
push userkgupta@mozilla.com
push dateWed, 14 Mar 2012 15:19:09 +0000
treeherdermozilla-central@936ef50fa498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs725095
milestone13.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 725095 - Address review comments in the widget code. r=blassey - Rip out a lot of unused code in AndroidFlexViewWrapper.* - Simplify the GetViewTransform JNI code - Move the references to CompositorParent and CompositorThread from AndroidBridge to nsWindow - Remove a bunch of logging and add some assertions and comments
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidFlexViewWrapper.cpp
widget/android/AndroidFlexViewWrapper.h
widget/android/AndroidGraphicBuffer.cpp
widget/android/AndroidJNI.cpp
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/nsAppShell.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -1061,29 +1061,28 @@ AndroidBridge::CallEglCreateWindowSurfac
 }
 
 static AndroidGLController sController;
 
 void
 AndroidBridge::RegisterCompositor()
 {
     ALOG_BRIDGE("AndroidBridge::RegisterCompositor");
-    JNIEnv *env = GetJNIForThread();
+    JNIEnv *env = GetJNIForThread();    // called on the compositor thread
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env, 3);
 
     jmethodID registerCompositor = env->GetStaticMethodID(jFlexSurfaceView, "registerCxxCompositor", "()Lorg/mozilla/gecko/gfx/GLController;");
 
     jobject glController = env->CallStaticObjectMethod(jFlexSurfaceView, registerCompositor);
 
     sController.Acquire(env, glController);
     sController.SetGLVersion(2);
-    __android_log_print(ANDROID_LOG_ERROR, "Gecko", "Registered Compositor");
 }
 
 EGLSurface
 AndroidBridge::ProvideEGLSurface()
 {
     sController.WaitForValidSurface();
     return sController.ProvideEGLSurface();
 }
@@ -1848,42 +1847,17 @@ AndroidBridge::IsTablet()
 
     return env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsTablet);
 }
 
 void
 AndroidBridge::SetCompositorParent(mozilla::layers::CompositorParent* aCompositorParent,
                                    ::base::Thread* aCompositorThread)
 {
-    mCompositorParent = aCompositorParent;
-    mCompositorThread = aCompositorThread;
-}
-
-void
-AndroidBridge::ScheduleComposite()
-{
-    if (mCompositorParent) {
-        mCompositorParent->ScheduleRenderOnCompositorThread();
-    }
-}
-
-void
-AndroidBridge::SchedulePauseComposition()
-{
-    if (mCompositorParent) {
-        mCompositorParent->SchedulePauseOnCompositorThread();
-    }
-}
-
-void
-AndroidBridge::ScheduleResumeComposition()
-{
-    if (mCompositorParent) {
-        mCompositorParent->ScheduleResumeOnCompositorThread();
-    }
+    nsWindow::SetCompositorParent(aCompositorParent, aCompositorThread);
 }
 
 void
 AndroidBridge::SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
@@ -1897,32 +1871,27 @@ AndroidBridge::SetPageSize(float aZoom, 
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
     client->SetPageSize(aZoom, aPageWidth, aPageHeight);
 }
 
 void
-AndroidBridge::SetViewTransformGetter(AndroidViewTransformGetter& aViewTransformGetter)
-{
-    mViewTransformGetter = &aViewTransformGetter;
-}
-
-void
 AndroidBridge::GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY)
 {
-    if (mViewTransformGetter) {
-        (*mViewTransformGetter)(aScrollOffset, aScaleX, aScaleY);
-    }
+    AndroidGeckoLayerClient *client = mLayerClient;
+    if (!client)
+        return;
+
+    client->GetViewTransform(aScrollOffset, aScaleX, aScaleY);
 }
 
 AndroidBridge::AndroidBridge()
 : mLayerClient(NULL)
-, mViewTransformGetter(NULL)
 {
 }
 
 AndroidBridge::~AndroidBridge()
 {
 }
 
 /* Implementation file */
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -401,22 +401,18 @@ public:
     bool IsTablet();
 
     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 SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight);
     void SetPageSize(float aZoom, float aPageWidth, float aPageHeight);
-    void SetViewTransformGetter(AndroidViewTransformGetter& aViewTransformGetter);
     void GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
 
     jobject CreateSurface();
     void DestroySurface(jobject surface);
     void ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend);
     void HideSurface(jobject surface);
 
 protected:
@@ -429,20 +425,16 @@ protected:
     JNIEnv *mJNIEnv;
     void *mThread;
 
     // the GeckoSurfaceView
     AndroidGeckoSurfaceView mSurfaceView;
 
     AndroidGeckoLayerClient *mLayerClient;
 
-    nsRefPtr<mozilla::layers::CompositorParent> mCompositorParent;
-    base::Thread *mCompositorThread;
-    AndroidViewTransformGetter *mViewTransformGetter;
-
     // the GeckoAppShell java class
     jclass mGeckoAppShellClass;
 
     AndroidBridge();
     ~AndroidBridge();
 
     bool Init(JNIEnv *jEnv, jclass jGeckoApp);
 
--- a/widget/android/AndroidFlexViewWrapper.cpp
+++ b/widget/android/AndroidFlexViewWrapper.cpp
@@ -31,200 +31,66 @@
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
 
 #include "AndroidFlexViewWrapper.h"
-
-
-static AndroidGLController sController;
-
-static const char *sEGLDisplayClassName = "com/google/android/gles_jni/EGLDisplayImpl";
-static const char *sEGLDisplayPointerFieldName = "mEGLDisplay";
-static jfieldID jEGLDisplayPointerField = 0;
+#include "nsDebug.h"
 
-static const char *sEGLConfigClassName = "com/google/android/gles_jni/EGLConfigImpl";
-static const char *sEGLConfigPointerFieldName = "mEGLConfig";
-static jfieldID jEGLConfigPointerField = 0;
+#define ASSERT_THREAD() \
+        NS_ASSERTION((void*)pthread_self() == mThread, "Something is calling AndroidGLController from the wrong thread!")
 
-static const char *sEGLContextClassName = "com/google/android/gles_jni/EGLContextImpl";
-static const char *sEGLContextPointerFieldName = "mEGLContext";
-static jfieldID jEGLContextPointerField = 0;
-
-static const char *sEGLSurfaceClassName = "com/google/android/gles_jni/EGLSurfaceImpl";
-static const char *sEGLSurfacePointerFieldName = "mEGLSurface";
 static jfieldID jEGLSurfacePointerField = 0;
 
 void AndroidEGLObject::Init(JNIEnv* aJEnv) {
     jclass jClass;
     jClass = reinterpret_cast<jclass>
-        (aJEnv->NewGlobalRef(aJEnv->FindClass(sEGLDisplayClassName)));
-    jEGLDisplayPointerField = aJEnv->GetFieldID(jClass, sEGLDisplayPointerFieldName, "I");
-    jClass = reinterpret_cast<jclass>
-        (aJEnv->NewGlobalRef(aJEnv->FindClass(sEGLConfigClassName)));
-    jEGLConfigPointerField = aJEnv->GetFieldID(jClass, sEGLConfigPointerFieldName, "I");
-    jClass = reinterpret_cast<jclass>
-        (aJEnv->NewGlobalRef(aJEnv->FindClass(sEGLContextClassName)));
-    jEGLContextPointerField = aJEnv->GetFieldID(jClass, sEGLContextPointerFieldName, "I");
-    jClass = reinterpret_cast<jclass>
-        (aJEnv->NewGlobalRef(aJEnv->FindClass(sEGLSurfaceClassName)));
-    jEGLSurfacePointerField = aJEnv->GetFieldID(jClass, sEGLSurfacePointerFieldName, "I");
+        (aJEnv->NewGlobalRef(aJEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl")));
+    jEGLSurfacePointerField = aJEnv->GetFieldID(jClass, "mEGLSurface", "I");
 }
 
 jmethodID AndroidGLController::jSetGLVersionMethod = 0;
-jmethodID AndroidGLController::jInitGLContextMethod = 0;
-jmethodID AndroidGLController::jDisposeGLContextMethod = 0;
-jmethodID AndroidGLController::jGetEGLDisplayMethod = 0;
-jmethodID AndroidGLController::jGetEGLConfigMethod = 0;
-jmethodID AndroidGLController::jGetEGLContextMethod = 0;
-jmethodID AndroidGLController::jGetEGLSurfaceMethod = 0;
-jmethodID AndroidGLController::jHasSurfaceMethod = 0;
-jmethodID AndroidGLController::jSwapBuffersMethod = 0;
-jmethodID AndroidGLController::jCheckForLostContextMethod = 0;
 jmethodID AndroidGLController::jWaitForValidSurfaceMethod = 0;
-jmethodID AndroidGLController::jGetWidthMethod = 0;
-jmethodID AndroidGLController::jGetHeightMethod = 0;
 jmethodID AndroidGLController::jProvideEGLSurfaceMethod = 0;
 
 void
 AndroidGLController::Init(JNIEnv *aJEnv)
 {
-    const char *className = "org/mozilla/gecko/gfx/GLController";
-    jclass jClass = reinterpret_cast<jclass>(aJEnv->NewGlobalRef(aJEnv->FindClass(className)));
+    jclass jClass = reinterpret_cast<jclass>(aJEnv->NewGlobalRef(aJEnv->FindClass("org/mozilla/gecko/gfx/GLController")));
 
     jSetGLVersionMethod = aJEnv->GetMethodID(jClass, "setGLVersion", "(I)V");
-    jInitGLContextMethod = aJEnv->GetMethodID(jClass, "initGLContext", "()V");
-    jDisposeGLContextMethod = aJEnv->GetMethodID(jClass, "disposeGLContext", "()V");
-    jGetEGLDisplayMethod = aJEnv->GetMethodID(jClass, "getEGLDisplay",
-                                              "()Ljavax/microedition/khronos/egl/EGLDisplay;");
-    jGetEGLConfigMethod = aJEnv->GetMethodID(jClass, "getEGLConfig",
-                                             "()Ljavax/microedition/khronos/egl/EGLConfig;");
-    jGetEGLContextMethod = aJEnv->GetMethodID(jClass, "getEGLContext",
-                                              "()Ljavax/microedition/khronos/egl/EGLContext;");
-    jGetEGLSurfaceMethod = aJEnv->GetMethodID(jClass, "getEGLSurface",
-                                              "()Ljavax/microedition/khronos/egl/EGLSurface;");
     jProvideEGLSurfaceMethod = aJEnv->GetMethodID(jClass, "provideEGLSurface",
                                                   "()Ljavax/microedition/khronos/egl/EGLSurface;");
-    jHasSurfaceMethod = aJEnv->GetMethodID(jClass, "hasSurface", "()Z");
-    jSwapBuffersMethod = aJEnv->GetMethodID(jClass, "swapBuffers", "()Z");
-    jCheckForLostContextMethod = aJEnv->GetMethodID(jClass, "checkForLostContext", "()Z");
     jWaitForValidSurfaceMethod = aJEnv->GetMethodID(jClass, "waitForValidSurface", "()V");
-    jGetWidthMethod = aJEnv->GetMethodID(jClass, "getWidth", "()I");
-    jGetHeightMethod = aJEnv->GetMethodID(jClass, "getHeight", "()I");
 }
 
 void
 AndroidGLController::Acquire(JNIEnv* aJEnv, jobject aJObj)
 {
     mJEnv = aJEnv;
+    mThread = (void*)pthread_self();
     mJObj = aJEnv->NewGlobalRef(aJObj);
 }
 
 void
-AndroidGLController::Acquire(JNIEnv* aJEnv)
-{
-    mJEnv = aJEnv;
-}
-
-void
-AndroidGLController::Release()
-{
-    if (mJObj) {
-        mJEnv->DeleteGlobalRef(mJObj);
-        mJObj = NULL;
-    }
-
-    mJEnv = NULL;
-}
-
-void
 AndroidGLController::SetGLVersion(int aVersion)
 {
+    ASSERT_THREAD();
     mJEnv->CallVoidMethod(mJObj, jSetGLVersionMethod, aVersion);
 }
 
-void
-AndroidGLController::InitGLContext()
-{
-    mJEnv->CallVoidMethod(mJObj, jInitGLContextMethod);
-}
-
-void
-AndroidGLController::DisposeGLContext()
-{
-    mJEnv->CallVoidMethod(mJObj, jDisposeGLContextMethod);
-}
-
-EGLDisplay
-AndroidGLController::GetEGLDisplay()
-{
-    jobject jObj = mJEnv->CallObjectMethod(mJObj, jGetEGLDisplayMethod);
-    return reinterpret_cast<EGLDisplay>(mJEnv->GetIntField(jObj, jEGLDisplayPointerField));
-}
-
-EGLConfig
-AndroidGLController::GetEGLConfig()
-{
-    jobject jObj = mJEnv->CallObjectMethod(mJObj, jGetEGLConfigMethod);
-    return reinterpret_cast<EGLConfig>(mJEnv->GetIntField(jObj, jEGLConfigPointerField));
-}
-
-EGLContext
-AndroidGLController::GetEGLContext()
-{
-    jobject jObj = mJEnv->CallObjectMethod(mJObj, jGetEGLContextMethod);
-    return reinterpret_cast<EGLContext>(mJEnv->GetIntField(jObj, jEGLContextPointerField));
-}
-
-EGLSurface
-AndroidGLController::GetEGLSurface()
-{
-    jobject jObj = mJEnv->CallObjectMethod(mJObj, jGetEGLSurfaceMethod);
-    return reinterpret_cast<EGLSurface>(mJEnv->GetIntField(jObj, jEGLSurfacePointerField));
-}
-
 EGLSurface
 AndroidGLController::ProvideEGLSurface()
 {
+    ASSERT_THREAD();
     jobject jObj = mJEnv->CallObjectMethod(mJObj, jProvideEGLSurfaceMethod);
     return reinterpret_cast<EGLSurface>(mJEnv->GetIntField(jObj, jEGLSurfacePointerField));
 }
 
-bool
-AndroidGLController::HasSurface()
-{
-    return mJEnv->CallBooleanMethod(mJObj, jHasSurfaceMethod);
-}
-
-bool
-AndroidGLController::SwapBuffers()
-{
-    return mJEnv->CallBooleanMethod(mJObj, jSwapBuffersMethod);
-}
-
-bool
-AndroidGLController::CheckForLostContext()
-{
-    return mJEnv->CallBooleanMethod(mJObj, jCheckForLostContextMethod);
-}
-
 void
 AndroidGLController::WaitForValidSurface()
 {
+    ASSERT_THREAD();
     mJEnv->CallVoidMethod(mJObj, jWaitForValidSurfaceMethod);
 }
-
-int
-AndroidGLController::GetWidth()
-{
-    return mJEnv->CallIntMethod(mJObj, jGetWidthMethod);
-}
-
-int
-AndroidGLController::GetHeight()
-{
-    return mJEnv->CallIntMethod(mJObj, jGetHeightMethod);
-}
-
-
--- a/widget/android/AndroidFlexViewWrapper.h
+++ b/widget/android/AndroidFlexViewWrapper.h
@@ -34,86 +34,42 @@
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
 
 #ifndef AndroidFlexViewWrapper_h__
 #define AndroidFlexViewWrapper_h__
 
 #include <jni.h>
-//#include <GLES/gl.h>
-//#include <GLES/glext.h>
 #include <cassert>
 #include <cstdlib>
 #include <pthread.h>
 #include <android/log.h>
 
-typedef void *NativeType;
-
 class AndroidEGLObject {
 public:
-    AndroidEGLObject(JNIEnv* aJEnv, jobject aJObj)
-    : mPtr(reinterpret_cast<NativeType>(aJEnv->GetIntField(aJObj, jPointerField))) {}
-
     static void Init(JNIEnv* aJEnv);
-
-    NativeType const& operator*() const {
-        return mPtr;
-    }
-
-private:
-    static jfieldID jPointerField;
-    static const char* sClassName;
-    static const char* sPointerFieldName;
-
-    const NativeType mPtr;
 };
 
-typedef void *EGLConfig;
-typedef void *EGLContext;
-typedef void *EGLDisplay;
 typedef void *EGLSurface;
 
 class AndroidGLController {
 public:
     static void Init(JNIEnv* aJEnv);
 
     void Acquire(JNIEnv *aJEnv, jobject aJObj);
-    void Acquire(JNIEnv *aJEnv);
-    void Release();
-
     void SetGLVersion(int aVersion);
-    void InitGLContext();
-    void DisposeGLContext();
-    EGLDisplay GetEGLDisplay();
-    EGLConfig GetEGLConfig();
-    EGLContext GetEGLContext();
-    EGLSurface GetEGLSurface();
     EGLSurface ProvideEGLSurface();
-    bool HasSurface();
-    bool SwapBuffers();
-    bool CheckForLostContext();
     void WaitForValidSurface();
-    int GetWidth();
-    int GetHeight();
 
 private:
     static jmethodID jSetGLVersionMethod;
-    static jmethodID jInitGLContextMethod;
-    static jmethodID jDisposeGLContextMethod;
-    static jmethodID jGetEGLDisplayMethod;
-    static jmethodID jGetEGLConfigMethod;
-    static jmethodID jGetEGLContextMethod;
-    static jmethodID jGetEGLSurfaceMethod;
-    static jmethodID jHasSurfaceMethod;
-    static jmethodID jSwapBuffersMethod;
-    static jmethodID jCheckForLostContextMethod;
     static jmethodID jWaitForValidSurfaceMethod;
-    static jmethodID jGetWidthMethod;
-    static jmethodID jGetHeightMethod;
     static jmethodID jProvideEGLSurfaceMethod;
 
+    // the JNIEnv for the compositor thread
     JNIEnv *mJEnv;
+    void *mThread;
     jobject mJObj;
 };
 
 #endif
 
--- a/widget/android/AndroidGraphicBuffer.cpp
+++ b/widget/android/AndroidGraphicBuffer.cpp
@@ -42,16 +42,18 @@
 #include "AndroidBridge.h"
 #include "mozilla/Preferences.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AndroidGraphicBuffer" , ## args)
 
 #define EGL_NATIVE_BUFFER_ANDROID 0x3140
 #define EGL_IMAGE_PRESERVED_KHR   0x30D2
 
+typedef void *EGLContext;
+typedef void *EGLDisplay;
 typedef PRUint32 EGLenum;
 typedef PRInt32 EGLint;
 typedef PRUint32 EGLBoolean;
 
 typedef gfxASurface::gfxImageFormat gfxImageFormat;
 
 #define EGL_TRUE 1
 #define EGL_FALSE 0
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -889,24 +889,24 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     NS_DispatchToMainThread(runnable);
 }
 
 #ifdef MOZ_JAVA_COMPOSITOR
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*, jclass)
 {
-    AndroidBridge::Bridge()->ScheduleComposite();
+    nsWindow::ScheduleComposite();
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_schedulePauseComposition(JNIEnv*, jclass)
 {
-    AndroidBridge::Bridge()->SchedulePauseComposition();
+    nsWindow::SchedulePauseComposition();
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*, jclass)
 {
-    AndroidBridge::Bridge()->ScheduleResumeComposition();
+    nsWindow::ScheduleResumeComposition();
 }
 
 #endif
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -655,19 +655,16 @@ AndroidPoint::Init(JNIEnv *jenv, jobject
     }
 }
 
 void
 AndroidGeckoLayerClient::Init(jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
     wrapped_obj = jobj;
-
-    // Register the view transform getter.
-    AndroidBridge::Bridge()->SetViewTransformGetter(mViewTransformGetter);
 }
 
 void
 AndroidLayerRendererFrame::Init(jobject jobj)
 {
     if (!isNull()) {
         Dispose();
     }
@@ -768,36 +765,55 @@ AndroidGeckoLayerClient::EndDrawing()
     AndroidBridge::AutoLocalJNIFrame jniFrame(env);
     return env->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
 }
 
 void
 AndroidGeckoLayerClient::SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight)
 {
     NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
-    JNIEnv *env = GetJNIForThread();
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AndroidBridge::AutoLocalJNIFrame jniFrame(env);
     return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, aOffsetX, aOffsetY, aZoom, aPageWidth, aPageHeight);
 }
 
 void
 AndroidGeckoLayerClient::SetPageSize(float aZoom, float aPageWidth, float aPageHeight)
 {
     NS_ASSERTION(!isNull(), "SetPageSize called on null layer client!");
-    JNIEnv *env = GetJNIForThread();
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AndroidBridge::AutoLocalJNIFrame jniFrame(env);
     return env->CallVoidMethod(wrapped_obj, jSetPageSize, aZoom, aPageWidth, aPageHeight);
 }
 
+void
+AndroidGeckoLayerClient::GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY)
+{
+    NS_ASSERTION(!isNull(), "GetViewTransform called on null layer client!");
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
+    if (!env)
+        return;
+
+    AndroidViewTransform viewTransform;
+    AndroidBridge::AutoLocalJNIFrame jniFrame(env);
+
+    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jGetViewTransformMethod);
+    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
+    viewTransform.Init(viewTransformJObj);
+
+    aScrollOffset = nsIntPoint(viewTransform.GetX(), viewTransform.GetY());
+    aScaleX = aScaleY = viewTransform.GetScale();
+}
+
 jobject
 AndroidGeckoSurfaceView::GetSoftwareDrawBitmap()
 {
     JNIEnv *env = AndroidBridge::GetJNIEnv();
     if (!env)
         return nsnull;
 
     return env->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBitmapMethod);
@@ -825,30 +841,16 @@ AndroidGeckoSurfaceView::GetSurface()
 
 jobject
 AndroidGeckoSurfaceView::GetSurfaceHolder()
 {
     return GetJNIForThread()->CallObjectMethod(wrapped_obj, jGetHolderMethod);
 }
 
 void
-AndroidGeckoLayerClient::GetViewTransform(AndroidViewTransform& aViewTransform)
-{
-    JNIEnv *env = GetJNIForThread();
-    NS_ABORT_IF_FALSE(env, "No JNI environment at GetViewTransform()!");
-    if (!env) {
-        return;
-    }
-
-    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jGetViewTransformMethod);
-    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
-    aViewTransform.Init(viewTransformJObj);
-}
-
-void
 AndroidGeckoLayerClient::CreateFrame(AndroidLayerRendererFrame& aFrame)
 {
     JNIEnv *env = GetJNIForThread();
     NS_ABORT_IF_FALSE(env, "No JNI environment at CreateFrame()!");
     if (!env) {
         return;
     }
 
@@ -952,29 +954,16 @@ AndroidViewTransform::GetScale()
 {
     JNIEnv *env = GetJNIForThread();
     if (!env)
         return 0.0f;
     return env->GetFloatField(wrapped_obj, jScaleField);
 }
 
 void
-AndroidGeckoLayerClientViewTransformGetter::operator()(nsIntPoint& aScrollOffset, float& aScaleX,
-                                                         float& aScaleY)
-{
-    AndroidViewTransform viewTransform;
-
-    AndroidBridge::AutoLocalJNIFrame jniFrame(GetJNIForThread());
-    mLayerClient.GetViewTransform(viewTransform);
-
-    aScrollOffset = nsIntPoint(viewTransform.GetX(), viewTransform.GetY());
-    aScaleX = aScaleY = viewTransform.GetScale();
-}
-
-void
 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 
     if (jobj) {
         mTop = jenv->GetIntField(jobj, jTopField);
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -148,35 +148,16 @@ protected:
 
     static jclass jRectClass;
     static jfieldID jBottomField;
     static jfieldID jLeftField;
     static jfieldID jRightField;
     static jfieldID jTopField;
 };
 
-
-/** A callback that retrieves the view transform. */
-class AndroidViewTransformGetter
-{
-public:
-    virtual void operator()(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY) = 0;
-};
-
-class AndroidGeckoLayerClientViewTransformGetter : public AndroidViewTransformGetter {
-public:
-    AndroidGeckoLayerClientViewTransformGetter(AndroidGeckoLayerClient& aLayerClient)
-    : mLayerClient(aLayerClient) {}
-
-    virtual void operator()(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
-
-private:
-    AndroidGeckoLayerClient& mLayerClient;
-};
-
 class AndroidViewTransform : public WrappedJavaObject {
 public:
     static void InitViewTransformClass(JNIEnv *jEnv);
 
     void Init(jobject jobj);
 
     AndroidViewTransform() {}
     AndroidViewTransform(jobject jobj) { Init(jobj); }
@@ -213,43 +194,38 @@ private:
 };
 
 class AndroidGeckoLayerClient : public WrappedJavaObject {
 public:
     static void InitGeckoLayerClientClass(JNIEnv *jEnv);
 
     void Init(jobject jobj);
 
-    AndroidGeckoLayerClient()
-    : mViewTransformGetter(*this) {}
-
-    AndroidGeckoLayerClient(jobject jobj)
-    : mViewTransformGetter(*this) { Init(jobj); }
+    AndroidGeckoLayerClient() {}
+    AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
 
     bool BeginDrawing(int aWidth, int aHeight, const nsAString &aMetadata);
     void EndDrawing();
     void SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight);
     void SetPageSize(float aZoom, float aPageWidth, float aPageHeight);
-    void GetViewTransform(AndroidViewTransform& aViewTransform);
+    void GetViewTransform(nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
     void CreateFrame(AndroidLayerRendererFrame& aFrame);
     void ActivateProgram();
     void DeactivateProgram();
 
 protected:
     static jclass jGeckoLayerClientClass;
     static jmethodID jBeginDrawingMethod;
     static jmethodID jEndDrawingMethod;
     static jmethodID jSetFirstPaintViewport;
     static jmethodID jSetPageSize;
     static jmethodID jGetViewTransformMethod;
     static jmethodID jCreateFrameMethod;
     static jmethodID jActivateProgramMethod;
     static jmethodID jDeactivateProgramMethod;
-
-    AndroidGeckoLayerClientViewTransformGetter mViewTransformGetter;
 };
 
 class AndroidGeckoSurfaceView : public WrappedJavaObject
 {
 public:
     static void InitGeckoSurfaceViewClass(JNIEnv *jEnv);
 
     AndroidGeckoSurfaceView() { }
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -459,17 +459,16 @@ nsAppShell::ProcessNextNativeEvent(bool 
             break;
 
         nsTArray<nsIntPoint> points = curEvent->Points();
         NS_ASSERTION(points.Length() == 2, "Screenshot event does not have enough coordinates");
         bridge->TakeScreenshot(domWindow, 0, 0, points[0].x, points[0].y, points[1].x, points[1].y, curEvent->MetaState(), scale);
         break;
     }
 
-
     case AndroidGeckoEvent::VIEWPORT:
     case AndroidGeckoEvent::BROADCAST: {
 
         if (curEvent->Characters().Length() == 0)
             break;
 
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -91,16 +91,18 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, n
 static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
 static gfxIntSize gAndroidScreenBounds;
 
 #ifdef ACCESSIBILITY
 bool nsWindow::sAccessibilityEnabled = false;
 #endif
 
 #ifdef MOZ_JAVA_COMPOSITOR
+#include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/CompositorParent.h"
 #include "mozilla/Mutex.h"
 #include "nsThreadUtils.h"
 #endif
 
 
 class ContentCreationNotifier;
 static nsCOMPtr<ContentCreationNotifier> gContentCreationNotifier;
 // A helper class to send updates when content processes
@@ -760,19 +762,16 @@ nsWindow::GetLayerManager(PLayersChild*,
         *aAllowRetaining = true;
     }
     if (mLayerManager) {
         return mLayerManager;
     }
 
     nsWindow *topWindow = TopWindow();
 
-    __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### nsWindow::GetLayerManager this=%p "
-                        "topWindow=%p", this, topWindow);
-
     if (!topWindow) {
         printf_stderr(" -- no topwindow\n");
         mLayerManager = CreateBasicLayerManager();
         return mLayerManager;
     }
 
     bool useCompositor =
         Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
@@ -1133,18 +1132,16 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
     }
 
     nsRefPtr<nsWindow> kungFuDeathGrip(this);
 
     AndroidBridge::AutoLocalJNIFrame jniFrame;
 #ifdef MOZ_JAVA_COMPOSITOR
     // We haven't been given a window-size yet, so do nothing
     if (gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0) {
-        __android_log_print(ANDROID_LOG_ERROR, "Gecko",
-                            "### No window size yet -- skipping draw!");
         return;
     }
 
     /*
      * Check to see whether the presentation shell corresponding to the document on the screen
      * is suppressing painting. If it is, we bail out, as continuing would result in a mismatch
      * between the content on the screen and the current viewport metrics.
      */
@@ -1152,59 +1149,39 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
         AndroidBridge::Bridge()->GetDrawMetadataProvider();
 
     layers::renderTraceEventStart("Check supress", "424242");
     bool paintingSuppressed = false;
     if (metadataProvider) {
         metadataProvider->PaintingSuppressed(&paintingSuppressed);
     }
     if (paintingSuppressed) {
-        __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### Painting suppressed!");
         return;
     }
     layers::renderTraceEventEnd("Check supress", "424242");
 
     layers::renderTraceEventStart("Get Drawable", "424343");
     nsAutoString metadata;
     if (metadataProvider) {
         metadataProvider->GetDrawMetadata(metadata);
     }
     layers::renderTraceEventEnd("Get Drawable", "424343");
 
-#if 0
-    // BEGIN HACK: gl layers
-    nsPaintEvent event(true, NS_PAINT, this);
-    nsIntRect tileRect(0, 0, gAndroidBounds.width, gAndroidBounds.height);
-    event.region = tileRect;
-#endif
-
     layers::renderTraceEventStart("Get surface", "424545");
     static unsigned char bits2[32 * 32 * 2];
     nsRefPtr<gfxImageSurface> targetSurface =
         new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * 2,
                             gfxASurface::ImageFormatRGB16_565);
     layers::renderTraceEventEnd("Get surface", "424545");
 
-#if 0
-    nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
-    AutoLayerManagerSetup setupLayerManager(this, ctx, BasicLayerManager::BUFFER_NONE);
-
-    nsEventStatus status;
-    status = DispatchEvent(&event);
-
-    return;
-    // END HACK: gl layers
-#endif
-
     layers::renderTraceEventStart("Check Bridge", "434444");
     nsIntRect dirtyRect = ae->Rect().Intersect(nsIntRect(0, 0, gAndroidBounds.width, gAndroidBounds.height));
 
     AndroidGeckoLayerClient &client = AndroidBridge::Bridge()->GetLayerClient();
     if (!client.BeginDrawing(gAndroidBounds.width, gAndroidBounds.height, metadata)) {
-        __android_log_print(ANDROID_LOG_ERROR, "Gecko", "### BeginDrawing returned false!");
         return;
     }
     layers::renderTraceEventEnd("Check Bridge", "434444");
 
     layers::renderTraceEventStart("Widget draw to", "434646");
     if (targetSurface->CairoStatus()) {
         ALOG("### Failed to create a valid surface from the bitmap");
     } else {
@@ -2306,10 +2283,48 @@ nsWindow::DrawWindowOverlay(LayerManager
 
     client.ActivateProgram();
     mLayerRendererFrame.DrawForeground();
     mLayerRendererFrame.EndDrawing();
     client.DeactivateProgram();
 
     mLayerRendererFrame.Dispose();
 }
+
+// off-main-thread compositor fields and functions
+
+nsRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent = 0;
+base::Thread * nsWindow::sCompositorThread = 0;
+
+void
+nsWindow::SetCompositorParent(mozilla::layers::CompositorParent* aCompositorParent,
+                              ::base::Thread* aCompositorThread)
+{
+    sCompositorParent = aCompositorParent;
+    sCompositorThread = aCompositorThread;
+}
+
+void
+nsWindow::ScheduleComposite()
+{
+    if (sCompositorParent) {
+        sCompositorParent->ScheduleRenderOnCompositorThread();
+    }
+}
+
+void
+nsWindow::SchedulePauseComposition()
+{
+    if (sCompositorParent) {
+        sCompositorParent->SchedulePauseOnCompositorThread();
+    }
+}
+
+void
+nsWindow::ScheduleResumeComposition()
+{
+    if (sCompositorParent) {
+        sCompositorParent->ScheduleResumeOnCompositorThread();
+    }
+}
+
 #endif
 
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -53,16 +53,20 @@
 #endif
 
 class gfxASurface;
 class nsIdleService;
 
 namespace mozilla {
     class AndroidGeckoEvent;
     class AndroidKeyEvent;
+
+    namespace layers {
+        class CompositorParent;
+    }
 }
 
 class nsWindow :
     public nsBaseWidget
 {
 public:
     using nsBaseWidget::GetLayerManager;
 
@@ -178,16 +182,22 @@ public:
 
 #ifdef ACCESSIBILITY
     static bool sAccessibilityEnabled;
 #endif
 
 #ifdef MOZ_JAVA_COMPOSITOR
     virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect);
     virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect);
+
+    static void SetCompositorParent(mozilla::layers::CompositorParent* aCompositorParent,
+                                    ::base::Thread* aCompositorThread);
+    static void ScheduleComposite();
+    static void SchedulePauseComposition();
+    static void ScheduleResumeComposition();
 #endif
 
 protected:
     void BringToFront();
     nsWindow *FindTopLevel();
     bool DrawTo(gfxASurface *targetSurface);
     bool DrawTo(gfxASurface *targetSurface, const nsIntRect &aRect);
     bool IsTopLevel();
@@ -248,12 +258,15 @@ private:
      * Generate the NS_GETACCESSIBLE event to get accessible for this window
      * and return it.
      */
     nsAccessible *DispatchAccessibleEvent();
 #endif // ACCESSIBILITY
 
 #ifdef MOZ_JAVA_COMPOSITOR
     mozilla::AndroidLayerRendererFrame mLayerRendererFrame;
+
+    static nsRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
+    static base::Thread *sCompositorThread;
 #endif
 };
 
 #endif /* NSWINDOW_H_ */