From 325ee148eecfb11c55bcba60d94ec063dcbcc936 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Wed, 23 Dec 2015 22:03:34 -0500 Subject: [PATCH] Bug 1227706 - Let GeckoView manage GLController instances; r=snorp GLController instances are associated with a particular nsWindow, rather than a particular View. Therefore, we need to let GeckoView manage GLController instances, as part of GeckoView's handling of saving and restoring states. --- .../java/org/mozilla/gecko/GeckoView.java | 27 +++--- .../org/mozilla/gecko/gfx/GLController.java | 14 +--- .../java/org/mozilla/gecko/gfx/LayerView.java | 22 ++++- widget/android/GeneratedJNINatives.h | 6 +- widget/android/GeneratedJNIWrappers.cpp | 3 - widget/android/GeneratedJNIWrappers.h | 19 +---- widget/android/jni/Refs.h | 6 ++ widget/android/nsWindow.cpp | 84 ++++++++++++++++++- widget/android/nsWindow.h | 4 + 9 files changed, 130 insertions(+), 55 deletions(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoView.java b/mobile/android/base/java/org/mozilla/gecko/GeckoView.java index 4c32ceb42c2d..98197eead836 100644 --- a/mobile/android/base/java/org/mozilla/gecko/GeckoView.java +++ b/mobile/android/base/java/org/mozilla/gecko/GeckoView.java @@ -13,6 +13,7 @@ import java.util.Set; import org.json.JSONException; import org.json.JSONObject; import org.mozilla.gecko.annotation.WrapForJNI; +import org.mozilla.gecko.gfx.GLController; import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.mozglue.GeckoLoader; import org.mozilla.gecko.mozglue.JNIObject; @@ -115,8 +116,8 @@ public class GeckoView extends LayerView @WrapForJNI private static final class Window extends JNIObject { - static native void open(Window instance, GeckoView view, int width, int height); - static native void setLayerClient(Object client); + static native void open(Window instance, GeckoView view, GLController glController, + int width, int height); @Override protected native void disposeNative(); native void close(); } @@ -155,14 +156,6 @@ public class GeckoView extends LayerView initializeView(EventDispatcher.getInstance()); - if (GeckoThread.isStateAtLeast(GeckoThread.State.JNI_READY)) { - Window.setLayerClient(getLayerClientObject()); - } else { - GeckoThread.queueNativeCallUntil(GeckoThread.State.JNI_READY, - Window.class, "setLayerClient", - Object.class, getLayerClientObject()); - } - // TODO: Fennec currently takes care of its own initialization, so this // flag is a hack used in Fennec to prevent GeckoView initialization. // This should go away once Fennec also uses GeckoView for @@ -225,17 +218,23 @@ public class GeckoView extends LayerView @Override public void onAttachedToWindow() { - super.onAttachedToWindow(); - final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); + // TODO: reuse GLController when restoring state. + final GLController glController = new GLController(); + if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) { - Window.open(window, this, metrics.widthPixels, metrics.heightPixels); + Window.open(window, this, glController, + metrics.widthPixels, metrics.heightPixels); + } else { GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class, - "open", window, GeckoView.class, this, + "open", window, GeckoView.class, this, glController, metrics.widthPixels, metrics.heightPixels); } + + setGLController(glController); + super.onAttachedToWindow(); } @Override diff --git a/mobile/android/base/java/org/mozilla/gecko/gfx/GLController.java b/mobile/android/base/java/org/mozilla/gecko/gfx/GLController.java index 496f9823932e..35aa159e4c03 100644 --- a/mobile/android/base/java/org/mozilla/gecko/gfx/GLController.java +++ b/mobile/android/base/java/org/mozilla/gecko/gfx/GLController.java @@ -33,9 +33,7 @@ public class GLController extends JNIObject { private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; private static final String LOGTAG = "GeckoGLController"; - private static GLController sInstance; - - private LayerView mView; + /* package */ LayerView mView; private boolean mServerSurfaceValid; private int mWidth, mHeight; @@ -90,15 +88,7 @@ public class GLController extends JNIObject { @WrapForJNI /* package */ native void syncInvalidateAndScheduleComposite(); - private GLController() { - } - - static GLController getInstance(LayerView view) { - if (sInstance == null) { - sInstance = new GLController(); - } - sInstance.mView = view; - return sInstance; + public GLController() { } synchronized void serverSurfaceDestroyed() { diff --git a/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java b/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java index 6c7d69837b91..96f98cd549f2 100644 --- a/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java +++ b/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java @@ -55,7 +55,7 @@ public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener private GeckoLayerClient mLayerClient; private PanZoomController mPanZoomController; private DynamicToolbarAnimator mToolbarAnimator; - private final GLController mGLController; + private GLController mGLController; private LayerRenderer mRenderer; /* Must be a PAINT_xxx constant */ private int mPaintState; @@ -106,7 +106,6 @@ public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener public LayerView(Context context, AttributeSet attrs) { super(context, attrs); - mGLController = GLController.getInstance(this); mPaintState = PAINT_START; mBackgroundColor = Color.WHITE; mFullScreenState = FullScreenState.NONE; @@ -199,6 +198,12 @@ public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener if (mRenderer != null) { mRenderer.destroy(); } + if (mGLController != null) { + if (mGLController.mView == this) { + mGLController.mView = null; + } + mGLController = null; + } Tabs.unregisterOnTabsChangedListener(this); } @@ -324,7 +329,6 @@ public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener // Don't expose GeckoLayerClient to things outside this package; only expose it as an Object GeckoLayerClient getLayerClient() { return mLayerClient; } - public Object getLayerClientObject() { return mLayerClient; } public PanZoomController getPanZoomController() { return mPanZoomController; } public DynamicToolbarAnimator getDynamicToolbarAnimator() { return mToolbarAnimator; } @@ -433,6 +437,18 @@ public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener return mListener; } + public void setGLController(final GLController glController) { + mGLController = glController; + glController.mView = this; + + if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) { + glController.setLayerClient(mLayerClient); + } else { + GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, + glController, "setLayerClient", mLayerClient); + } + } + public GLController getGLController() { return mGLController; } diff --git a/widget/android/GeneratedJNINatives.h b/widget/android/GeneratedJNINatives.h index 6569d70f3276..26d143a9e158 100644 --- a/widget/android/GeneratedJNINatives.h +++ b/widget/android/GeneratedJNINatives.h @@ -203,11 +203,7 @@ public: mozilla::jni::MakeNativeMethod( mozilla::jni::NativeStub - ::template Wrap<&Impl::Open>), - - mozilla::jni::MakeNativeMethod( - mozilla::jni::NativeStub - ::template Wrap<&Impl::SetLayerClient>) + ::template Wrap<&Impl::Open>) }; }; diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 942c59611cd4..1edf3822bf87 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -1113,9 +1113,6 @@ constexpr char GeckoView::Window::DisposeNative_t::signature[]; constexpr char GeckoView::Window::Open_t::name[]; constexpr char GeckoView::Window::Open_t::signature[]; -constexpr char GeckoView::Window::SetLayerClient_t::name[]; -constexpr char GeckoView::Window::SetLayerClient_t::signature[]; - constexpr char PrefsHelper::name[]; constexpr char PrefsHelper::GetPrefsById_t::name[]; diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index 3bf69a86e50e..a12370188b68 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -2983,27 +2983,12 @@ public: typedef mozilla::jni::Args< Window::Param, GeckoView::Param, + mozilla::jni::Object::Param, int32_t, int32_t> Args; static constexpr char name[] = "open"; static constexpr char signature[] = - "(Lorg/mozilla/gecko/GeckoView$Window;Lorg/mozilla/gecko/GeckoView;II)V"; - static const bool isStatic = true; - static const bool isMultithreaded = true; - static const mozilla::jni::ExceptionMode exceptionMode = - mozilla::jni::ExceptionMode::ABORT; - }; - -public: - struct SetLayerClient_t { - typedef Window Owner; - typedef void ReturnType; - typedef void SetterType; - typedef mozilla::jni::Args< - mozilla::jni::Object::Param> Args; - static constexpr char name[] = "setLayerClient"; - static constexpr char signature[] = - "(Ljava/lang/Object;)V"; + "(Lorg/mozilla/gecko/GeckoView$Window;Lorg/mozilla/gecko/GeckoView;Lorg/mozilla/gecko/gfx/GLController;II)V"; static const bool isStatic = true; static const bool isMultithreaded = true; static const mozilla::jni::ExceptionMode exceptionMode = diff --git a/widget/android/jni/Refs.h b/widget/android/jni/Refs.h index 1f8647b872d4..867add4c4ea2 100644 --- a/widget/android/jni/Refs.h +++ b/widget/android/jni/Refs.h @@ -148,6 +148,12 @@ public: return Ref(static_cast(obj)); } + // Construct a Ref form a generic object reference. + static Ref From(const RefBase& obj) + { + return Ref(obj.Get()); + } + // Get the raw JNI reference. JNIType Get() const { diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 9deea86f060a..3fa43802cf6c 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -268,7 +268,7 @@ public: // Create and attach a window. static void Open(const jni::ClassObject::LocalRef& aCls, GeckoView::Window::Param aWindow, - GeckoView::Param aView, + GeckoView::Param aView, jni::Object::Param aGLController, int32_t aWidth, int32_t aHeight); // Set the active layer client object @@ -374,6 +374,77 @@ public: void OnImeUpdateComposition(int32_t aStart, int32_t aEnd); }; +/** + * GLController has some unique requirements for its native calls, so make it + * separate from GeckoViewSupport. + */ +class nsWindow::GLControllerSupport final + : public GLController::Natives + , public SupportsWeakPtr + , public UsesGeckoThreadProxy +{ + nsWindow& window; + GLController::GlobalRef mGLController; + +public: + typedef GLController::Natives Base; + + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLControllerSupport); + + GLControllerSupport(nsWindow* aWindow, + const GLController::LocalRef& aInstance) + : window(*aWindow) + , mGLController(aInstance) + { + Reattach(aInstance); + } + + ~GLControllerSupport() + { + GLController::GlobalRef glController(mozilla::Move(mGLController)); + nsAppShell::gAppShell->PostEvent([glController] { + GLControllerSupport::DisposeNative(GLController::LocalRef( + jni::GetGeckoThreadEnv(), glController)); + }); + } + + void Reattach(const GLController::LocalRef& aInstance) + { + Base::AttachNative(aInstance, this); + } + + /** + * GLController methods + */ +public: + using Base::DisposeNative; + + void SetLayerClient(jni::Object::Param aClient) + { + // TODO: implement. + } + + void CreateCompositor(int32_t aWidth, int32_t aHeight) + { + // TODO: implement. + } + + void PauseCompositor() + { + // TODO: implement. + } + + void SyncResumeResizeCompositor(int32_t aWidth, int32_t aHeight) + { + // TODO: implement. + } + + void SyncInvalidateAndScheduleComposite() + { + // TODO: implement. + } +}; + nsWindow::GeckoViewSupport::~GeckoViewSupport() { // Disassociate our GeckoEditable instance with our native object. @@ -387,6 +458,7 @@ nsWindow::GeckoViewSupport::~GeckoViewSupport() nsWindow::GeckoViewSupport::Open(const jni::ClassObject::LocalRef& aCls, GeckoView::Window::Param aWindow, GeckoView::Param aView, + jni::Object::Param aGLController, int32_t aWidth, int32_t aHeight) { MOZ_ASSERT(NS_IsMainThread()); @@ -400,6 +472,10 @@ nsWindow::GeckoViewSupport::Open(const jni::ClassObject::LocalRef& aCls, gGeckoViewWindow->mGeckoViewSupport->Reattach( GeckoView::Window::LocalRef(aCls.Env(), aWindow)); + MOZ_ASSERT(gGeckoViewWindow->mGLControllerSupport); + gGeckoViewWindow->mGLControllerSupport->Reattach(GLController::LocalRef( + aCls.Env(), GLController::Ref::From(aGLController))); + // Associate our previous GeckoEditable with the new GeckoView. gGeckoViewWindow->mGeckoViewSupport->mEditable->OnViewChange(aView); return; @@ -443,6 +519,11 @@ nsWindow::GeckoViewSupport::Open(const jni::ClassObject::LocalRef& aCls, window->mGeckoViewSupport = mozilla::MakeUnique( window, GeckoView::Window::LocalRef(aCls.Env(), aWindow), aView); + // Attach the GLController to the new window. + window->mGLControllerSupport = mozilla::MakeUnique( + window, GLController::LocalRef( + aCls.Env(), GLController::Ref::From(aGLController))); + gGeckoViewWindow = window; } @@ -470,6 +551,7 @@ nsWindow::InitNatives() { nsWindow::GeckoViewSupport::Base::Init(); nsWindow::GeckoViewSupport::EditableBase::Init(); + nsWindow::GLControllerSupport::Init(); } nsWindow* diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 99082bf0b5ff..7ad18bc26408 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -53,6 +53,10 @@ private: // nullptr for nsWindows that were not opened from GeckoView. mozilla::UniquePtr mGeckoViewSupport; + class GLControllerSupport; + // Object that implements native GLController calls. + mozilla::UniquePtr mGLControllerSupport; + public: static void OnGlobalAndroidEvent(mozilla::AndroidGeckoEvent *ae); static mozilla::gfx::IntSize GetAndroidScreenBounds();