--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -1922,25 +1922,32 @@ CreateSurfaceForWindow(nsIWidget *aWidge
EGLSurface surface;
#ifdef DEBUG
sEGLLibrary.DumpEGLConfig(config);
#endif
#ifdef MOZ_WIDGET_ANDROID
+ printf_stderr("... requesting window surface from bridge\n");
+
// On Android, we have to ask Java to make the eglCreateWindowSurface
// call for us. See GLHelpers.java for a description of why.
//
// We also only have one true "window", so we just use it directly and ignore
// what was passed in.
+ AndroidGeckoSurfaceView& sview = mozilla::AndroidBridge::Bridge()->SurfaceView();
+ if (sview.isNull()) {
+ printf_stderr("got null surface\n");
+ return NULL;
+ }
+
printf_stderr("... requesting window surface from bridge\n");
surface = mozilla::AndroidBridge::Bridge()->
- CallEglCreateWindowSurface(EGL_DISPLAY(), config,
- mozilla::AndroidBridge::Bridge()->SurfaceView());
+ CallEglCreateWindowSurface(EGL_DISPLAY(), config, sview);
printf_stderr("got surface %p\n", surface);
#else
surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, GET_NATIVE_WINDOW(aWidget), 0);
#endif
#ifdef MOZ_WIDGET_GONK
gScreenBounds.x = 0;
gScreenBounds.y = 0;
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -38,16 +38,20 @@
*
* ***** END LICENSE BLOCK ***** */
#include "CompositorParent.h"
#include "ShadowLayersParent.h"
#include "LayerManagerOGL.h"
#include "nsIWidget.h"
+#if defined(MOZ_WIDGET_ANDROID)
+#include "AndroidBridge.h"
+#endif
+
namespace mozilla {
namespace layers {
CompositorParent::CompositorParent(nsIWidget* aWidget)
: mStopped(false), mWidget(aWidget)
{
MOZ_COUNT_CTOR(CompositorParent);
}
@@ -121,16 +125,22 @@ CompositorParent::ShadowLayersUpdated()
SetShadowProperties(root);
}
ScheduleComposition();
}
PLayersParent*
CompositorParent::AllocPLayers(const LayersBackend &backendType)
{
+#ifdef MOZ_WIDGET_ANDROID
+ // Registering with the compositor will create the surface view that
+ // the layer manager expects to attach to.
+ RegisterCompositorWithJava();
+#endif
+
if (backendType == LayerManager::LAYERS_OPENGL) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
mWidget = NULL;
mLayerManager = layerManager;
if (!layerManager->Initialize()) {
NS_ERROR("Failed to init OGL Layers");
return NULL;
@@ -149,11 +159,20 @@ CompositorParent::AllocPLayers(const Lay
bool
CompositorParent::DeallocPLayers(PLayersParent* actor)
{
delete actor;
return true;
}
+#ifdef MOZ_WIDGET_ANDROID
+void
+CompositorParent::RegisterCompositorWithJava()
+{
+ mozilla::AndroidBridge::Bridge()->RegisterCompositor();
+}
+#endif
+
+
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -70,16 +70,26 @@ public:
protected:
virtual PLayersParent* AllocPLayers(const LayersBackend &backendType);
virtual bool DeallocPLayers(PLayersParent* aLayers);
private:
void ScheduleComposition();
void Composite();
+ // Platform specific functions
+#ifdef MOZ_WIDGET_ANDROID
+ /**
+ * Register the compositor thread with the Java native thread.
+ * This will replace the temporary compositor with the real
+ * Gecko compositor thread.
+ **/
+ void RegisterCompositorWithJava();
+#endif
+
nsRefPtr<LayerManager> mLayerManager;
bool mStopped;
nsIWidget* mWidget;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
};
} // layers
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -39,17 +39,16 @@
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko;
import org.mozilla.gecko.gfx.FloatSize;
import org.mozilla.gecko.gfx.GeckoSoftwareLayerClient;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.LayerController;
-import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PlaceholderLayerClient;
import org.mozilla.gecko.gfx.RectUtils;
import org.mozilla.gecko.gfx.ViewportMetrics;
import org.mozilla.gecko.Tab.HistoryEntry;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
@@ -1527,17 +1526,17 @@ abstract public class GeckoApp
*
* TODO: Fall back to a built-in screenshot of the Fennec Start page for a nice first-
* run experience, perhaps?
*/
mLayerController = new LayerController(this);
mPlaceholderLayerClient = PlaceholderLayerClient.createInstance(this);
mLayerController.setLayerClient(mPlaceholderLayerClient);
- mGeckoLayout.addView(mLayerController.getView(), 0);
+ mGeckoLayout.addView(mLayerController.getView().getAndroidView(), 0);
}
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - UI almost up");
if (!sTryCatchAttached) {
sTryCatchAttached = true;
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -36,17 +36,17 @@
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.gfx.GeckoSoftwareLayerClient;
import org.mozilla.gecko.gfx.LayerController;
-import org.mozilla.gecko.gfx.LayerView;
+import org.mozilla.gecko.gfx.AbstractLayerView;
import java.io.*;
import java.lang.reflect.*;
import java.nio.*;
import java.nio.channels.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
@@ -468,19 +468,18 @@ public class GeckoAppShell
// and go
GeckoAppShell.nativeRun(combinedArgs);
}
// Called on the UI thread after Gecko loads.
private static void geckoLoaded() {
final LayerController layerController = GeckoApp.mAppContext.getLayerController();
- LayerView v = layerController.getView();
- mInputConnection = GeckoInputConnection.create(v);
- v.setInputConnectionHandler(mInputConnection);
+ AbstractLayerView v = layerController.getView();
+ mInputConnection = v.setInputConnectionHandler();
layerController.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
return true;
}
});
layerController.notifyLayerClientOfGeometryChange();
@@ -551,17 +550,17 @@ public class GeckoAppShell
if (tmp != null)
tmp.countDown();
}
static Sensor gAccelerometerSensor = null;
static Sensor gOrientationSensor = null;
public static void enableDeviceMotion(boolean enable) {
- LayerView v = GeckoApp.mAppContext.getLayerController().getView();
+ AbstractLayerView v = GeckoApp.mAppContext.getLayerController().getView();
SensorManager sm = (SensorManager) v.getContext().getSystemService(Context.SENSOR_SERVICE);
if (gAccelerometerSensor == null || gOrientationSensor == null) {
gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
if (enable) {
@@ -575,17 +574,17 @@ public class GeckoAppShell
if (gOrientationSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor);
}
}
public static void enableLocation(final boolean enable) {
getMainHandler().post(new Runnable() {
public void run() {
- LayerView v = GeckoApp.mAppContext.getLayerController().getView();
+ //AbstractLayerView v = GeckoApp.mAppContext.getLayerController().getView();
LocationManager lm = (LocationManager)
GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
if (enable) {
Criteria criteria = new Criteria();
String provider = lm.getBestProvider(criteria, true);
if (provider == null)
@@ -1049,25 +1048,25 @@ public class GeckoAppShell
public static String showFilePicker(String aFilters) {
return GeckoApp.mAppContext.
showFilePicker(getMimeTypeFromExtensions(aFilters));
}
public static void performHapticFeedback(boolean aIsLongPress) {
LayerController layerController = GeckoApp.mAppContext.getLayerController();
- LayerView layerView = layerController.getView();
- layerView.performHapticFeedback(aIsLongPress ?
+ AbstractLayerView layerView = layerController.getView();
+ layerView.getAndroidView().performHapticFeedback(aIsLongPress ?
HapticFeedbackConstants.LONG_PRESS :
HapticFeedbackConstants.VIRTUAL_KEY);
}
private static Vibrator vibrator() {
LayerController layerController = GeckoApp.mAppContext.getLayerController();
- LayerView layerView = layerController.getView();
+ AbstractLayerView layerView = layerController.getView();
return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
}
public static void vibrate(long milliseconds) {
vibrator().vibrate(milliseconds);
}
@@ -1723,17 +1722,17 @@ public class GeckoAppShell
public static void emitGeckoAccessibilityEvent (int eventType, String role, String text, String description, boolean enabled, boolean checked, boolean password) {
AccessibilityManager accessibilityManager =
(AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
if (!accessibilityManager.isEnabled())
return;
LayerController layerController = GeckoApp.mAppContext.getLayerController();
- LayerView layerView = layerController.getView();
+ AbstractLayerView layerView = layerController.getView();
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setClassName(layerView.getClass().getName() + "$" + role);
event.setPackageName(GeckoApp.mAppContext.getPackageName());
event.setEnabled(enabled);
event.setChecked(checked);
event.setPassword(password);
event.setContentDescription(description);
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -354,17 +354,17 @@ public class GeckoInputConnection
mEditable.toString()));
setEditable(text);
}
}
if (mUpdateRequest == null)
return;
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (imm == null) {
imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null)
return;
}
mUpdateExtract.flags = 0;
@@ -392,17 +392,17 @@ public class GeckoInputConnection
int b = Selection.getSelectionEnd(content);
if (start != a || end != b) {
if (DEBUG) Log.d(LOGTAG, String.format(". . . notifySelectionChange: current editable selection: [%d, %d]", a, b));
super.setSelection(start, end);
}
}
if (imm != null && imm.isFullscreenMode()) {
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
imm.updateSelection(v, start, end, -1, -1);
}
}
public void reset() {
mComposing = false;
mBatchMode = false;
mUpdateRequest = null;
@@ -537,17 +537,17 @@ public class GeckoInputConnection
break;
}
if (isPreIme && mIMEState != IME_STATE_DISABLED &&
(event.getMetaState() & KeyEvent.META_ALT_ON) != 0)
// Let active IME process pre-IME key events
return false;
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
// KeyListener returns true if it handled the event for us.
if (mIMEState == IME_STATE_DISABLED ||
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
keyCode == KeyEvent.KEYCODE_TAB ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
!mKeyListener.onKeyDown(v, mEditable, keyCode, event)) {
@@ -579,34 +579,34 @@ public class GeckoInputConnection
break;
}
if (isPreIme && mIMEState != IME_STATE_DISABLED &&
(event.getMetaState() & KeyEvent.META_ALT_ON) != 0)
// Let active IME process pre-IME key events
return false;
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (mIMEState == IME_STATE_DISABLED ||
keyCode == KeyEvent.KEYCODE_ENTER ||
keyCode == KeyEvent.KEYCODE_DEL ||
(event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 ||
!mKeyListener.onKeyUp(v, mEditable, keyCode, event))
GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
return true;
}
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
GeckoAppShell.sendEventToGecko(new GeckoEvent(event));
return true;
}
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
InputMethodManager imm = (InputMethodManager)
v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInputFromWindow(v.getWindowToken(),
imm.SHOW_FORCED, 0);
return true;
default:
@@ -616,17 +616,17 @@ public class GeckoInputConnection
}
public boolean isIMEEnabled() {
// make sure this picks up PASSWORD and PLUGIN states as well
return mIMEState != IME_STATE_DISABLED;
}
public void notifyIME(int type, int state) {
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (v == null)
return;
switch (type) {
case NOTIFY_IME_RESETINPUTSTATE:
if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: reset");
@@ -660,33 +660,33 @@ public class GeckoInputConnection
IMEStateUpdater.resetIME();
break;
}
}
public void notifyIMEEnabled(int state, String typeHint,
String actionHint, boolean landscapeFS)
{
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (v == null)
return;
/* When IME is 'disabled', IME processing is disabled.
In addition, the IME UI is hidden */
mIMEState = state;
mIMETypeHint = typeHint;
mIMEActionHint = actionHint;
mIMELandscapeFS = landscapeFS;
IMEStateUpdater.enableIME();
}
public void notifyIMEChange(String text, int start, int end, int newEnd) {
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (v == null)
return;
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null)
return;
@@ -735,17 +735,17 @@ public class GeckoInputConnection
}
public void run() {
if (DEBUG) Log.d(LOGTAG, "IME: run()");
synchronized(IMEStateUpdater.class) {
instance = null;
}
- View v = GeckoApp.mAppContext.getLayerController().getView();
+ View v = GeckoApp.mAppContext.getLayerController().getView().getAndroidView();
if (DEBUG) Log.d(LOGTAG, "IME: v="+v);
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null)
return;
if (mReset)
imm.restartInput(v);
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -88,16 +88,17 @@ FENNEC_JAVA_FILES = \
GlobalHistory.java \
LinkPreference.java \
ProfileMigrator.java \
PromptService.java \
SurfaceLockInfo.java \
Tab.java \
Tabs.java \
TabsTray.java \
+ gfx/AbstractLayerView.java \
gfx/BitmapUtils.java \
gfx/BufferedCairoImage.java \
gfx/CairoGLInfo.java \
gfx/CairoImage.java \
gfx/CairoUtils.java \
gfx/FloatSize.java \
gfx/GeckoSoftwareLayerClient.java \
gfx/InputConnectionHandler.java \
@@ -115,16 +116,17 @@ FENNEC_JAVA_FILES = \
gfx/RectUtils.java \
gfx/ScrollbarLayer.java \
gfx/SingleTileLayer.java \
gfx/TextLayer.java \
gfx/TextureReaper.java \
gfx/TileLayer.java \
gfx/ViewportMetrics.java \
gfx/WidgetTileLayer.java \
+ gfx/layers/OGLSurfaceView.java \
ui/Axis.java \
ui/PanZoomController.java \
ui/SubdocumentScrollHelper.java \
GeckoNetworkManager.java \
$(NULL)
ifdef MOZ_WEBSMS_BACKEND
FENNEC_JAVA_FILES += GeckoSmsManager.java
--- a/mobile/android/base/gfx/Layer.java
+++ b/mobile/android/base/gfx/Layer.java
@@ -48,17 +48,17 @@ import org.mozilla.gecko.FloatUtils;
public abstract class Layer {
private final ReentrantLock mTransactionLock;
private boolean mInTransaction;
private Point mOrigin;
private Point mNewOrigin;
private float mResolution;
private float mNewResolution;
- private LayerView mView;
+ private AbstractLayerView mView;
public Layer() {
mTransactionLock = new ReentrantLock();
mOrigin = new Point(0, 0);
mResolution = 1.0f;
}
/**
@@ -98,17 +98,17 @@ public abstract class Layer {
/**
* Call this before modifying the layer. Note that, for TileLayers, "modifying the layer"
* includes altering the underlying CairoImage in any way. Thus you must call this function
* before modifying the byte buffer associated with this layer.
*
* This function may block, so you should never call this on the main UI thread.
*/
- public void beginTransaction(LayerView aView) {
+ public void beginTransaction(AbstractLayerView aView) {
if (mTransactionLock.isHeldByCurrentThread())
throw new RuntimeException("Nested transactions are not supported");
mTransactionLock.lock();
mView = aView;
mInTransaction = true;
mNewResolution = mResolution;
}
--- a/mobile/android/base/gfx/LayerClient.java
+++ b/mobile/android/base/gfx/LayerClient.java
@@ -49,21 +49,21 @@ public abstract class LayerClient {
public LayerController getLayerController() { return mLayerController; }
public void setLayerController(LayerController layerController) {
mLayerController = layerController;
}
/**
* A utility function for calling Layer.beginTransaction with the
- * appropriate LayerView.
+ * appropriate AbstractLayerView.
*/
public void beginTransaction(Layer aLayer) {
if (mLayerController != null) {
- LayerView view = mLayerController.getView();
+ AbstractLayerView view = mLayerController.getView();
if (view != null) {
aLayer.beginTransaction(view);
return;
}
}
aLayer.beginTransaction();
}
--- a/mobile/android/base/gfx/LayerController.java
+++ b/mobile/android/base/gfx/LayerController.java
@@ -36,17 +36,17 @@
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.gfx.LayerClient;
-import org.mozilla.gecko.gfx.LayerView;
+import org.mozilla.gecko.gfx.AbstractLayerView;
import org.mozilla.gecko.ui.PanZoomController;
import org.mozilla.gecko.GeckoApp;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.graphics.PointF;
@@ -65,17 +65,17 @@ import java.lang.Math;
* to a higher-level view.
*
* Many methods require that the monitor be held, with a synchronized (controller) { ... } block.
*/
public class LayerController {
private static final String LOGTAG = "GeckoLayerController";
private Layer mRootLayer; /* The root layer. */
- private LayerView mView; /* The main rendering view. */
+ private AbstractLayerView mView; /* The main rendering view. */
private Context mContext; /* The current context. */
private ViewportMetrics mViewportMetrics; /* The current viewport metrics. */
private PanZoomController mPanZoomController;
/*
* The panning and zooming controller, which interprets pan and zoom gestures for us and
* updates our visible rect appropriately.
*/
@@ -113,17 +113,17 @@ public class LayerController {
}
public void setForceRedraw() {
mForceRedraw = true;
}
public LayerClient getLayerClient() { return mLayerClient; }
public Layer getRoot() { return mRootLayer; }
- public LayerView getView() { return mView; }
+ public AbstractLayerView getView() { return mView; }
public Context getContext() { return mContext; }
public ViewportMetrics getViewportMetrics() { return mViewportMetrics; }
public RectF getViewport() {
return mViewportMetrics.getViewport();
}
public FloatSize getViewportSize() {
@@ -330,13 +330,13 @@ public class LayerController {
/*
* Gesture detection. This is handled only at a high level in this class; we dispatch to the
* pan/zoom controller to do the dirty work.
*/
public boolean onTouchEvent(MotionEvent event) {
if (mPanZoomController.onTouchEvent(event))
return true;
if (mOnTouchListener != null)
- return mOnTouchListener.onTouch(mView, event);
+ return mOnTouchListener.onTouch(mView.getAndroidView(), event);
return false;
}
}
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -37,17 +37,17 @@
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.BufferedCairoImage;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.Layer.RenderContext;
import org.mozilla.gecko.gfx.LayerController;
-import org.mozilla.gecko.gfx.LayerView;
+import org.mozilla.gecko.gfx.AbstractLayerView;
import org.mozilla.gecko.gfx.NinePatchTileLayer;
import org.mozilla.gecko.gfx.SingleTileLayer;
import org.mozilla.gecko.gfx.TextureReaper;
import org.mozilla.gecko.gfx.TextLayer;
import org.mozilla.gecko.gfx.TileLayer;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Point;
@@ -77,32 +77,32 @@ public class LayerRenderer implements GL
* The amount of time a frame is allowed to take to render before we declare it a dropped
* frame.
*/
private static final int MAX_FRAME_TIME = 16; /* 1000 ms / 60 FPS */
private static final int FRAME_RATE_METER_WIDTH = 64;
private static final int FRAME_RATE_METER_HEIGHT = 32;
- private final LayerView mView;
+ private final AbstractLayerView mView;
private final SingleTileLayer mCheckerboardLayer;
private final NinePatchTileLayer mShadowLayer;
private final TextLayer mFrameRateLayer;
private final ScrollbarLayer mHorizScrollLayer;
private final ScrollbarLayer mVertScrollLayer;
private final FadeRunnable mFadeRunnable;
private RenderContext mLastPageContext;
private int mMaxTextureSize;
// Dropped frames display
private int[] mFrameTimings;
private int mCurrentFrame, mFrameTimingsSum, mDroppedFrames;
private boolean mShowFrameRate;
- public LayerRenderer(LayerView view) {
+ public LayerRenderer(AbstractLayerView view) {
mView = view;
LayerController controller = view.getController();
CairoImage checkerboardImage = new BufferedCairoImage(controller.getCheckerboardPattern());
mCheckerboardLayer = new SingleTileLayer(true, checkerboardImage);
CairoImage shadowImage = new BufferedCairoImage(controller.getShadowPattern());
--- a/mobile/android/base/gfx/LayerView.java
+++ b/mobile/android/base/gfx/LayerView.java
@@ -35,32 +35,35 @@
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.FloatSize;
import org.mozilla.gecko.gfx.InputConnectionHandler;
import org.mozilla.gecko.gfx.LayerController;
+import org.mozilla.gecko.GeckoInputConnection;
import android.content.Context;
import android.opengl.GLSurfaceView;
+import android.view.View;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.ScaleGestureDetector;
+import android.widget.RelativeLayout;
/**
* A view rendered by the layer compositor.
*
* This view delegates to LayerRenderer to actually do the drawing. Its role is largely that of a
* mediator between the LayerRenderer and the LayerController.
*/
-public class LayerView extends GLSurfaceView {
+public class LayerView extends GLSurfaceView implements AbstractLayerView {
private Context mContext;
private LayerController mController;
private InputConnectionHandler mInputConnectionHandler;
private LayerRenderer mRenderer;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private long mRenderTime;
private boolean mRenderTimeReset;
@@ -94,18 +97,20 @@ public class LayerView extends GLSurface
public LayerController getController() { return mController; }
/** The LayerRenderer calls this to indicate that the window has changed size. */
public void setViewportSize(IntSize size) {
mController.setViewportSize(new FloatSize(size));
}
- public void setInputConnectionHandler(InputConnectionHandler handler) {
- mInputConnectionHandler = handler;
+ public GeckoInputConnection setInputConnectionHandler() {
+ mInputConnectionHandler = GeckoInputConnection.create(this);
+ setInputConnectionHandler(mInputConnectionHandler);
+ return mInputConnectionHandler;
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (mInputConnectionHandler != null)
return mInputConnectionHandler.onCreateInputConnection(outAttrs);
return null;
}
@@ -166,10 +171,14 @@ public class LayerView extends GLSurface
mRenderTimeReset = false;
return System.nanoTime() - mRenderTime;
}
}
public int getMaxTextureSize() {
return mRenderer.getMaxTextureSize();
}
+
+ public View getAndroidView() {
+ return this;
+ }
}
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -182,16 +182,18 @@ AndroidBridge::Init(JNIEnv *jEnv,
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
+ jOGLSurfaceView = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("org/mozilla/gecko/gfx/layers/OGLSurfaceView"));
+
InitAndroidJavaWrappers(jEnv);
// jEnv should NOT be cached here by anything -- the jEnv here
// is not valid for the real gecko main thread, which is set
// at SetMainThread time.
return true;
}
@@ -870,17 +872,17 @@ AndroidBridge::ShowInputMethodPicker()
ALOG_BRIDGE("AndroidBridge::ShowInputMethodPicker");
mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jShowInputMethodPicker);
}
void *
AndroidBridge::CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoSurfaceView &sview)
{
ALOG_BRIDGE("AndroidBridge::CallEglCreateWindowSurface");
- AutoLocalJNIFrame jniFrame;
+ AutoLocalJNIFrame jniFrame(GetJNIForThread());
/*
* This is basically:
*
* s = EGLContext.getEGL().eglCreateWindowSurface(new EGLDisplayImpl(dpy),
* new EGLConfigImpl(config),
* view.getHolder(), null);
* return s.mEGLSurface;
@@ -911,16 +913,27 @@ AndroidBridge::CallEglCreateWindowSurfac
jfieldID sfield = mJNIEnv->GetFieldID(jEGLSurfaceImplClass, "mEGLSurface", "I");
jint realSurface = mJNIEnv->GetIntField(surf, sfield);
return (void*) realSurface;
}
+void
+AndroidBridge::RegisterCompositor()
+{
+ ALOG_BRIDGE("AndroidBridge::RegisterCompositor");
+ AutoLocalJNIFrame jniFrame(GetJNIForThread());
+
+ jmethodID registerCompositor = GetJNIForThread()->GetStaticMethodID(jOGLSurfaceView, "registerCompositor", "()V");
+
+ GetJNIForThread()->CallStaticVoidMethod(jOGLSurfaceView, registerCompositor);
+}
+
bool
AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, PRInt32* aInt)
{
ALOG_BRIDGE("AndroidBridge::GetStaticIntField %s", fieldName);
AutoLocalJNIFrame jniFrame(3);
jclass cls = mJNIEnv->FindClass(className);
if (!cls)
return false;
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -280,16 +280,19 @@ public:
int mEntries;
JNIEnv* mJNIEnv;
};
/* See GLHelpers.java as to why this is needed */
void *CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoSurfaceView& surfaceView);
+ // Switch Java to composite with the Gecko Compositor thread
+ void RegisterCompositor();
+
bool GetStaticStringField(const char *classID, const char *field, nsAString &result);
bool GetStaticIntField(const char *className, const char *fieldName, PRInt32* aInt);
void SetKeepScreenOn(bool on);
void ScanMedia(const nsAString& aFile, const nsACString& aMimeType);
@@ -457,16 +460,18 @@ protected:
// stuff we need for CallEglCreateWindowSurface
jclass jEGLSurfaceImplClass;
jclass jEGLContextImplClass;
jclass jEGLConfigImplClass;
jclass jEGLDisplayImplClass;
jclass jEGLContextClass;
jclass jEGL10Class;
+ jclass jOGLSurfaceView;
+
// calls we've dlopened from libjnigraphics.so
int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);
int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
void* (*ANativeWindow_fromSurface)(JNIEnv *env, jobject surface);
void (*ANativeWindow_release)(void *window);
int (*ANativeWindow_setBuffersGeometry)(void *window, int width, int height, int format);
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -103,16 +103,18 @@ extern "C" {
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 bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass);
#endif
+
+ NS_EXPORT void JNICALL Java_org_mozilla_gfx_layers_OGLSurfaceView_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
}
/*
* Incoming JNI methods
*/
NS_EXPORT void JNICALL
@@ -139,16 +141,22 @@ Java_org_mozilla_gecko_GeckoAppShell_pro
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject obj)
{
AndroidBridge::Bridge()->SetSurfaceView(jenv->NewGlobalRef(obj));
}
NS_EXPORT void JNICALL
+Java_org_mozilla_gfx_layers_OGLSurfaceView_setSurfaceView(JNIEnv *jenv, jclass, jobject obj)
+{
+ AndroidBridge::Bridge()->SetSurfaceView(jenv->NewGlobalRef(obj));
+}
+
+NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject obj)
{
AndroidBridge::Bridge()->SetSoftwareLayerClient(jenv->NewGlobalRef(obj));
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *jenv, jclass jc)
{
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -194,16 +194,24 @@ AndroidGeckoSurfaceView::InitGeckoSurfac
jBeginDrawingMethod = getMethod("beginDrawing", "()I");
jGetSoftwareDrawBitmapMethod = getMethod("getSoftwareDrawBitmap", "()Landroid/graphics/Bitmap;");
jGetSoftwareDrawBufferMethod = getMethod("getSoftwareDrawBuffer", "()Ljava/nio/ByteBuffer;");
jEndDrawingMethod = getMethod("endDrawing", "()V");
jDraw2DBitmapMethod = getMethod("draw2D", "(Landroid/graphics/Bitmap;II)V");
jDraw2DBufferMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;I)V");
jGetSurfaceMethod = getMethod("getSurface", "()Landroid/view/Surface;");
jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;");
+#else
+ initInit();
+
+ jGeckoSurfaceViewClass = getClassGlobalRef("org/mozilla/gecko/gfx/layers/OGLSurfaceView");
+
+ jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;");
+
+
#endif
}
void
AndroidLocation::InitLocationClass(JNIEnv *jEnv)
{
initInit();
@@ -651,17 +659,17 @@ jobject
AndroidGeckoSurfaceView::GetSurface()
{
return JNI()->CallObjectMethod(wrapped_obj, jGetSurfaceMethod);
}
jobject
AndroidGeckoSurfaceView::GetSurfaceHolder()
{
- return JNI()->CallObjectMethod(wrapped_obj, jGetHolderMethod);
+ return GetJNIForThread()->CallObjectMethod(wrapped_obj, jGetHolderMethod);
}
void
AndroidRect::Init(JNIEnv *jenv, jobject jobj)
{
NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
wrapped_obj = jobj;
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -776,35 +776,44 @@ nsWindow::GetLayerManager(PLayersChild*,
if (!mUseAcceleratedRendering ||
sFailedToCreateGLContext)
{
printf_stderr(" -- creating basic, not accelerated\n");
mLayerManager = CreateBasicLayerManager();
return mLayerManager;
}
- if (!sGLContext) {
- // the window we give doesn't matter here
- sGLContext = mozilla::gl::GLContextProvider::CreateForWindow(this);
+ bool useCompositor =
+ Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
+
+ if (useCompositor) {
+ CreateCompositor();
}
- if (sGLContext) {
- nsRefPtr<mozilla::layers::LayerManagerOGL> layerManager =
- new mozilla::layers::LayerManagerOGL(this);
+ if (!mLayerManager) {
+ if (!sGLContext) {
+ // the window we give doesn't matter here
+ sGLContext = mozilla::gl::GLContextProvider::CreateForWindow(this);
+ }
+
+ if (sGLContext) {
+ nsRefPtr<mozilla::layers::LayerManagerOGL> layerManager =
+ new mozilla::layers::LayerManagerOGL(this);
- if (layerManager && layerManager->Initialize(sGLContext))
- mLayerManager = layerManager;
- sValidSurface = true;
- }
+ if (layerManager && layerManager->Initialize(sGLContext))
+ mLayerManager = layerManager;
+ sValidSurface = true;
+ }
- if (!sGLContext || !mLayerManager) {
- sGLContext = nsnull;
- sFailedToCreateGLContext = true;
+ if (!sGLContext || !mLayerManager) {
+ sGLContext = nsnull;
+ sFailedToCreateGLContext = true;
- mLayerManager = CreateBasicLayerManager();
+ mLayerManager = CreateBasicLayerManager();
+ }
}
return mLayerManager;
}
gfxASurface*
nsWindow::GetThebesSurface()
{