[Libreoffice-commits] core.git: Branch 'feature/android-viewer' - 3 commits - android/experimental
Tomaž Vajngerl
tomaz.vajngerl at collabora.com
Mon Jun 23 07:37:09 PDT 2014
android/experimental/LOAndroid/.idea/misc.xml | 3
android/experimental/LOAndroid2/.idea/libraries/appcompat_v7_19_1_0.xml | 10
android/experimental/LOAndroid2/.idea/libraries/support_v4_19_1_0.xml | 11
android/experimental/LOAndroid2/.idea/modules.xml | 1
android/experimental/LOAndroid2/LOAndroid2.iml | 12
android/experimental/LOAndroid2/app/app.iml | 4
android/experimental/LOAndroid2/app/build.gradle | 1
android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOEvent.java | 6
android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitShell.java | 13
android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java | 64 -
android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LibreOfficeMainActivity.java | 18
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CairoGLInfo.java | 35
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CheckerboardImage.java | 6
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FlexibleGLSurfaceView.java | 218 ++++
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FloatSize.java | 25
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLController.java | 279 +++++
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLThread.java | 181 +++
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoGLLayerClient.java | 265 +++++
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoLayerClient.java | 414 ++++++++
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java | 435 ++------
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/Layer.java | 71 +
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/LayerController.java | 101 +-
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/LayerRenderer.java | 499 ++++++----
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/LayerView.java | 27
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/MultiTileLayer.java | 190 ++-
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/RectUtils.java | 47
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/ScrollbarLayer.java | 282 ++++-
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/SingleTileLayer.java | 51 -
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/TextureReaper.java | 7
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/TileLayer.java | 74 -
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/ViewTransform.java | 51 +
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/ViewportMetrics.java | 126 +-
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/VirtualLayer.java | 80 +
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/WidgetTileLayer.java | 69 +
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/ui/Axis.java | 4
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/ui/PanZoomController.java | 30
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java | 54 -
android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/ui/SubdocumentScrollHelper.java | 16
android/experimental/LOAndroid2/app/src/main/res/menu/main.xml | 3
39 files changed, 2801 insertions(+), 982 deletions(-)
New commits:
commit 94bfbe588ea1716f86f9993eacbf66eb97efe7c6
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Mon Jun 23 11:03:19 2014 +0200
LODroid2: GLES2 fixes, code cleanup
Change-Id: I368f8caaf0433387a330a63182aab292defef0ca
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
index 08c4949..ea3472b 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
@@ -28,8 +28,8 @@ public class LOKitThread extends Thread {
private boolean draw() throws InterruptedException {
final LibreOfficeMainActivity application = LibreOfficeMainActivity.mAppContext;
- Bitmap bitmap = application.getLayerClient().getLayerController().getDrawable16("dummy_page");
- bitmap = convert(bitmap, Bitmap.Config.RGB_565);
+ Bitmap bitmap = application.getLayerClient().getLayerController().getDrawable("docu");
+ //bitmap = convert(bitmap, Bitmap.Config.ARGB_8888);
StringWriter stringWriter = new StringWriter();
@@ -41,11 +41,11 @@ public class LOKitThread extends Thread {
writer.name("y").value(0);
writer.name("width").value(bitmap.getWidth());
writer.name("height").value(bitmap.getHeight());
- writer.name("pageWidth").value(1000);
- writer.name("pageHeight").value(5000);
+ writer.name("pageWidth").value(bitmap.getWidth());
+ writer.name("pageHeight").value(bitmap.getHeight());
writer.name("offsetX").value(0);
writer.name("offsetY").value(0);
- writer.name("zoom").value(1.0);
+ writer.name("zoom").value(0.5);
} else {
writer.name("x").value(mViewportMetrics.getOrigin().x);
writer.name("y").value(mViewportMetrics.getOrigin().y);
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
index 97cbfb4..fa1d5ad 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
@@ -80,7 +80,7 @@ public class GeckoSoftwareLayerClient extends GeckoLayerClient {
public GeckoSoftwareLayerClient(Context context) {
super(context);
- mFormat = CairoImage.FORMAT_RGB16_565;
+ mFormat = CairoImage.FORMAT_ARGB32;
mCairoImage = new CairoImage() {
@Override
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/MultiTileLayer.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/MultiTileLayer.java
index 3ade6c1..3514b42 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/MultiTileLayer.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/MultiTileLayer.java
@@ -38,30 +38,26 @@
package org.mozilla.gecko.gfx;
-import org.mozilla.gecko.gfx.CairoImage;
-import org.mozilla.gecko.gfx.IntSize;
-import org.mozilla.gecko.gfx.SingleTileLayer;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
-import android.util.Log;
+
import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
import java.util.ArrayList;
/**
* Encapsulates the logic needed to draw a layer made of multiple tiles.
- *
+ * <p/>
* TODO: Support repeating.
*/
public class MultiTileLayer extends Layer {
private static final String LOGTAG = "GeckoMultiTileLayer";
private final CairoImage mImage;
+ private final ArrayList<SubTile> mTiles;
private IntSize mTileSize;
private IntSize mBufferSize;
- private final ArrayList<SubTile> mTiles;
public MultiTileLayer(CairoImage image, IntSize tileSize) {
super();
@@ -181,7 +177,7 @@ public class MultiTileLayer extends Layer {
if (!RectF.intersects(layerBounds, context.viewport)) {
if (firstDirtyTile == null)
firstDirtyTile = layer;
- dirtyTiles ++;
+ dirtyTiles++;
invalid = true;
} else {
// This tile intersects with the screen and is dirty,
@@ -207,7 +203,7 @@ public class MultiTileLayer extends Layer {
if (!screenUpdateDone && firstDirtyTile != null) {
firstDirtyTile.setSkipTextureUpdate(false);
firstDirtyTile.performUpdates(context);
- dirtyTiles --;
+ dirtyTiles--;
}
return (dirtyTiles == 0);
@@ -217,7 +213,7 @@ public class MultiTileLayer extends Layer {
IntSize size = getSize();
for (SubTile layer : mTiles) {
if (!inTransaction) {
- layer.beginTransaction(null);
+ layer.beginTransaction();
}
if (origin != null) {
@@ -246,11 +242,11 @@ public class MultiTileLayer extends Layer {
}
@Override
- public void beginTransaction(LayerView aView) {
- super.beginTransaction(aView);
+ public void beginTransaction() {
+ super.beginTransaction();
for (SubTile layer : mTiles) {
- layer.beginTransaction(aView);
+ layer.beginTransaction();
}
}
commit b71cf4031426f8bf4e282143c92e3774d79bbdb7
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Mon Jun 23 11:00:59 2014 +0200
LODroid2: Remove sdk v7 and v4 support libraries
Change-Id: I41a30d44c44cb439dc2e60e212eea18b00f316dd
diff --git a/android/experimental/LOAndroid2/.idea/libraries/appcompat_v7_19_1_0.xml b/android/experimental/LOAndroid2/.idea/libraries/appcompat_v7_19_1_0.xml
deleted file mode 100644
index 7efbfdf..0000000
--- a/android/experimental/LOAndroid2/.idea/libraries/appcompat_v7_19_1_0.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<component name="libraryTable">
- <library name="appcompat-v7-19.1.0">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/19.1.0/classes.jar!/" />
- <root url="file://$PROJECT_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/19.1.0/res" />
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
-</component>
\ No newline at end of file
diff --git a/android/experimental/LOAndroid2/.idea/libraries/support_v4_19_1_0.xml b/android/experimental/LOAndroid2/.idea/libraries/support_v4_19_1_0.xml
deleted file mode 100644
index 1ca1ac6..0000000
--- a/android/experimental/LOAndroid2/.idea/libraries/support_v4_19_1_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="support-v4-19.1.0">
- <CLASSES>
- <root url="jar://$USER_HOME$/Programs/android-sdk-linux/extras/android/m2repository/com/android/support/support-v4/19.1.0/support-v4-19.1.0.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$USER_HOME$/Programs/android-sdk-linux/extras/android/m2repository/com/android/support/support-v4/19.1.0/support-v4-19.1.0-sources.jar!/" />
- </SOURCES>
- </library>
-</component>
\ No newline at end of file
diff --git a/android/experimental/LOAndroid2/app/app.iml b/android/experimental/LOAndroid2/app/app.iml
index 34b87a5..2fc60e0 100644
--- a/android/experimental/LOAndroid2/app/app.iml
+++ b/android/experimental/LOAndroid2/app/app.iml
@@ -61,8 +61,6 @@
</content>
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" exported="" name="appcompat-v7-19.1.0" level="project" />
- <orderEntry type="library" exported="" name="support-v4-19.1.0" level="project" />
</component>
</module>
diff --git a/android/experimental/LOAndroid2/app/build.gradle b/android/experimental/LOAndroid2/app/build.gradle
index 7e98dd4c..6053f91 100644
--- a/android/experimental/LOAndroid2/app/build.gradle
+++ b/android/experimental/LOAndroid2/app/build.gradle
@@ -20,5 +20,4 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.android.support:appcompat-v7:19.+'
}
diff --git a/android/experimental/LOAndroid2/app/src/main/res/menu/main.xml b/android/experimental/LOAndroid2/app/src/main/res/menu/main.xml
index 6768fd3..e9709c9 100644
--- a/android/experimental/LOAndroid2/app/src/main/res/menu/main.xml
+++ b/android/experimental/LOAndroid2/app/src/main/res/menu/main.xml
@@ -4,6 +4,5 @@
tools:context="org.libreoffice.MainActivity" >
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
- android:orderInCategory="100"
- app:showAsAction="never" />
+ android:orderInCategory="100" />
</menu>
diff --git a/android/experimental/LOAndroid2/gradlew b/android/experimental/LOAndroid2/gradlew
old mode 100644
new mode 100755
commit ae642816dae500310d1ae2db1542d5651953bd92
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.com>
Date: Tue Jun 17 13:05:33 2014 +0200
LOAndroid2: use GLES2, latest GeckoSoftwareLayerClient
Additionally add GeckoGLLayerClient as an alternative LayerClient
Change-Id: I250b5d806f520231ad9a9b84ef8387e8830bb364
diff --git a/android/experimental/LOAndroid/.idea/misc.xml b/android/experimental/LOAndroid/.idea/misc.xml
index d0225fc..589a3ed 100644
--- a/android/experimental/LOAndroid/.idea/misc.xml
+++ b/android/experimental/LOAndroid/.idea/misc.xml
@@ -3,6 +3,9 @@
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
+ <component name="EntryPointsManager">
+ <entry_points version="2.0" />
+ </component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
diff --git a/android/experimental/LOAndroid2/.idea/modules.xml b/android/experimental/LOAndroid2/.idea/modules.xml
index f08135d..d5e166f 100644
--- a/android/experimental/LOAndroid2/.idea/modules.xml
+++ b/android/experimental/LOAndroid2/.idea/modules.xml
@@ -3,6 +3,7 @@
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/LOAndroid.iml" filepath="$PROJECT_DIR$/LOAndroid.iml" />
+ <module fileurl="file://$PROJECT_DIR$/LOAndroid2.iml" filepath="$PROJECT_DIR$/LOAndroid2.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
diff --git a/android/experimental/LOAndroid2/LOAndroid2.iml b/android/experimental/LOAndroid2/LOAndroid2.iml
new file mode 100644
index 0000000..edb62a6
--- /dev/null
+++ b/android/experimental/LOAndroid2/LOAndroid2.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/android/experimental/LOAndroid2/app/app.iml b/android/experimental/LOAndroid2/app/app.iml
index e89240b..34b87a5 100644
--- a/android/experimental/LOAndroid2/app/app.iml
+++ b/android/experimental/LOAndroid2/app/app.iml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="LOAndroid" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="LOAndroid2" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOEvent.java b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOEvent.java
index a539669..bf4f98b 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOEvent.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOEvent.java
@@ -20,7 +20,7 @@ public class LOEvent {
ViewportMetrics viewportMetrics;
- public LOEvent(int type, int width, int height, int widthPixels, int heightPixels) {
+ public LOEvent(int type, int width, int height, int widthPixels, int heightPixels, int tileWidth, int tileHeight) {
mType = type;
mTypeString = "Size Changed";
}
@@ -45,8 +45,8 @@ public class LOEvent {
return new LOEvent(DRAW, rect);
}
- public static LOEvent sizeChanged(int width, int height, int widthPixels, int heightPixels) {
- return new LOEvent(SIZE_CHANGED, width, height, widthPixels, heightPixels);
+ public static LOEvent sizeChanged(int width, int height, int widthPixels, int heightPixels, int tileWidth, int tileHeight) {
+ return new LOEvent(SIZE_CHANGED, width, height, widthPixels, heightPixels, tileWidth, tileHeight);
}
public static LOEvent tileSize(IntSize tileSize) {
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitShell.java b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitShell.java
index 69b634c..9dde790 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitShell.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitShell.java
@@ -115,4 +115,17 @@ public class LOKitShell {
layerController.notifyLayerClientOfGeometryChange();*/
}
+
+ public static void viewSizeChanged() {
+ }
+
+ public static void scheduleComposite() {
+ }
+
+ public static void schedulePauseComposition() {
+ }
+
+ public static void scheduleResumeComposition() {
+
+ }
}
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
index 37bb51c..08c4949 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LOKitThread.java
@@ -4,6 +4,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Rect;
import android.util.JsonWriter;
import org.mozilla.gecko.gfx.ViewportMetrics;
@@ -11,8 +12,6 @@ import org.mozilla.gecko.gfx.ViewportMetrics;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
-import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -26,28 +25,11 @@ public class LOKitThread extends Thread {
LOKitThread() {
}
- private void draw() throws InterruptedException {
+ private boolean draw() throws InterruptedException {
final LibreOfficeMainActivity application = LibreOfficeMainActivity.mAppContext;
- Bitmap bitmap = application.getSoftwareLayerClient().getLayerController().getDrawable16("dummy_page");
- bitmap = convert(bitmap, Bitmap.Config.RGB_565);
-
- application.getSoftwareLayerClient().beginDrawing(bitmap.getWidth(), bitmap.getHeight());
- //application.getSoftwareLayerClient().beginDrawing(500,500);
-
- ByteBuffer buffer = application.getSoftwareLayerClient().getBuffer();
- bitmap.copyPixelsToBuffer(buffer.asIntBuffer());
-
- /*short mainColor16 = convertTo16Bit(rand.nextInt());
-
- short[] mainPattern = new short[500];
- Arrays.fill(mainPattern, mainColor16);
-
- buffer.rewind();
- ShortBuffer shortBuffer = buffer.asShortBuffer();
- for (int i = 0; i < 500; i++) {
- shortBuffer.put(mainPattern);
- }*/
+ Bitmap bitmap = application.getLayerClient().getLayerController().getDrawable16("dummy_page");
+ bitmap = convert(bitmap, Bitmap.Config.RGB_565);
StringWriter stringWriter = new StringWriter();
@@ -64,7 +46,6 @@ public class LOKitThread extends Thread {
writer.name("offsetX").value(0);
writer.name("offsetY").value(0);
writer.name("zoom").value(1.0);
- writer.name("allowZoom").value(true);
} else {
writer.name("x").value(mViewportMetrics.getOrigin().x);
writer.name("y").value(mViewportMetrics.getOrigin().y);
@@ -75,7 +56,6 @@ public class LOKitThread extends Thread {
writer.name("offsetX").value(mViewportMetrics.getViewportOffset().x);
writer.name("offsetY").value(mViewportMetrics.getViewportOffset().y);
writer.name("zoom").value(mViewportMetrics.getZoomFactor());
- writer.name("allowZoom").value(mViewportMetrics.getAllowZoom());
}
writer.name("backgroundColor").value("rgb(255,255,255)");
writer.endObject();
@@ -83,15 +63,24 @@ public class LOKitThread extends Thread {
} catch (IOException ex) {
}
- application.getSoftwareLayerClient().endDrawing(0, 0, bitmap.getWidth(), bitmap.getHeight(), stringWriter.toString(), false);
- //application.getSoftwareLayerClient().endDrawing(0, 0, 500, 500, stringWriter.toString(), false);
- application.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- application.getSoftwareLayerClient().handleMessage("Viewport:UpdateLater", null);
- }
- });
+ Rect bufferRect = application.getLayerClient().beginDrawing(bitmap.getWidth(), bitmap.getHeight(), 256, 256, stringWriter.toString(), false);
+
+ if (bufferRect == null) {
+ return false;
+ }
+ ByteBuffer buffer = application.getLayerClient().lockBuffer();
+ bitmap.copyPixelsToBuffer(buffer.asIntBuffer());
+ application.getLayerClient().unlockBuffer();
+ application.getLayerClient().endDrawing(0, 0, bitmap.getWidth(), bitmap.getHeight());
+
+ application.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ application.getLayerClient().handleMessage("Viewport:UpdateLater", null);
+ }
+ });
+ return true;
}
private short convertTo16Bit(int color) {
@@ -119,9 +108,8 @@ public class LOKitThread extends Thread {
if (!gEvents.isEmpty()) {
processEvent(gEvents.poll());
} else {
- if(!drawn) {
- draw();
- drawn = true;
+ if (!drawn) {
+ drawn = draw();
}
Thread.sleep(100L);
}
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LibreOfficeMainActivity.java
index a4fdf03..934464d 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -23,7 +23,7 @@ public class LibreOfficeMainActivity extends Activity {
private LinearLayout mMainLayout;
private RelativeLayout mGeckoLayout;
private static LayerController mLayerController;
- private static GeckoSoftwareLayerClient mSoftwareLayerClient;
+ private static GeckoSoftwareLayerClient mLayerClient;
private static LOKitThread sLOKitThread;
public static LibreOfficeMainActivity mAppContext;
@@ -74,8 +74,12 @@ public class LibreOfficeMainActivity extends Activity {
if (mLayerController == null) {
mLayerController = new LayerController(this);
- mSoftwareLayerClient = new GeckoSoftwareLayerClient(this);
- mLayerController.setLayerClient(mSoftwareLayerClient);
+
+ Log.e(LOGTAG, "### Creating GeckoSoftwareLayerClient");
+ mLayerClient = new GeckoSoftwareLayerClient(this);
+ Log.e(LOGTAG, "### Done creating GeckoSoftwareLayerClient");
+
+ mLayerController.setLayerClient(mLayerClient);
mGeckoLayout.addView(mLayerController.getView(), 0);
}
@@ -88,7 +92,11 @@ public class LibreOfficeMainActivity extends Activity {
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - UI almost up");
}
- public static GeckoSoftwareLayerClient getSoftwareLayerClient() {
- return mSoftwareLayerClient;
+ public static GeckoSoftwareLayerClient getLayerClient() {
+ return mLayerClient;
+ }
+
+ public static LayerController getLayerController() {
+ return mLayerController;
}
}
\ No newline at end of file
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CairoGLInfo.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CairoGLInfo.java
index 16417e1..bd4eedc 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CairoGLInfo.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CairoGLInfo.java
@@ -39,7 +39,9 @@ package org.mozilla.gecko.gfx;
import javax.microedition.khronos.opengles.GL10;
-/** Information needed to render Cairo bitmaps using OpenGL ES. */
+/**
+ * Information needed to render Cairo bitmaps using OpenGL ES.
+ */
public class CairoGLInfo {
public final int internalFormat;
public final int format;
@@ -47,20 +49,23 @@ public class CairoGLInfo {
public CairoGLInfo(int cairoFormat) {
switch (cairoFormat) {
- case CairoImage.FORMAT_ARGB32:
- internalFormat = format = GL10.GL_RGBA; type = GL10.GL_UNSIGNED_BYTE;
- break;
- case CairoImage.FORMAT_RGB24:
- internalFormat = format = GL10.GL_RGB; type = GL10.GL_UNSIGNED_BYTE;
- break;
- case CairoImage.FORMAT_RGB16_565:
- internalFormat = format = GL10.GL_RGB; type = GL10.GL_UNSIGNED_SHORT_5_6_5;
- break;
- case CairoImage.FORMAT_A8:
- case CairoImage.FORMAT_A1:
- throw new RuntimeException("Cairo FORMAT_A1 and FORMAT_A8 unsupported");
- default:
- throw new RuntimeException("Unknown Cairo format");
+ case CairoImage.FORMAT_ARGB32:
+ internalFormat = format = GL10.GL_RGBA;
+ type = GL10.GL_UNSIGNED_BYTE;
+ break;
+ case CairoImage.FORMAT_RGB24:
+ internalFormat = format = GL10.GL_RGB;
+ type = GL10.GL_UNSIGNED_BYTE;
+ break;
+ case CairoImage.FORMAT_RGB16_565:
+ internalFormat = format = GL10.GL_RGB;
+ type = GL10.GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case CairoImage.FORMAT_A8:
+ case CairoImage.FORMAT_A1:
+ throw new RuntimeException("Cairo FORMAT_A1 and FORMAT_A8 unsupported");
+ default:
+ throw new RuntimeException("Unknown Cairo format");
}
}
}
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CheckerboardImage.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CheckerboardImage.java
index f9ff966..392d7e8 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CheckerboardImage.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/CheckerboardImage.java
@@ -38,7 +38,6 @@
package org.mozilla.gecko.gfx;
import org.libreoffice.LOKitShell;
-//import org.mozilla.gecko.GeckoAppShell;
import android.graphics.Color;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
@@ -62,7 +61,7 @@ public class CheckerboardImage extends CairoImage {
/** Creates a new checkerboard image. */
public CheckerboardImage() {
int bpp = CairoUtils.bitsPerPixelForCairoFormat(FORMAT);
- mBuffer = /*GeckoAppShell*/LOKitShell.allocateDirectBuffer(SIZE * SIZE * bpp / 8);
+ mBuffer = LOKitShell.allocateDirectBuffer(SIZE * SIZE * bpp / 8);
update(true, Color.WHITE);
}
@@ -146,7 +145,7 @@ public class CheckerboardImage extends CairoImage {
protected void finalize() throws Throwable {
try {
if (mBuffer != null) {
- /*GeckoAppShell*/LOKitShell.freeDirectBuffer(mBuffer);
+ LOKitShell.freeDirectBuffer(mBuffer);
}
} finally {
super.finalize();
@@ -168,3 +167,4 @@ public class CheckerboardImage extends CairoImage {
return FORMAT;
}
}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FlexibleGLSurfaceView.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FlexibleGLSurfaceView.java
new file mode 100644
index 0000000..dc20077
--- /dev/null
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FlexibleGLSurfaceView.java
@@ -0,0 +1,218 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton at mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+package org.mozilla.gecko.gfx;
+
+//import org.mozilla.gecko.GeckoApp;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import org.libreoffice.LibreOfficeMainActivity;
+
+public class FlexibleGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+ private static final String LOGTAG = "GeckoFlexibleGLSurfaceView";
+
+ private GLSurfaceView.Renderer mRenderer;
+ private GLThread mGLThread; // Protected by this class's monitor.
+ private GLController mController;
+ private Listener mListener;
+
+ public FlexibleGLSurfaceView(Context context) {
+ super(context);
+ init();
+ }
+
+ public FlexibleGLSurfaceView(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ init();
+ }
+
+ public void init() {
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(this);
+ holder.setFormat(PixelFormat.RGB_565);
+
+ mController = new GLController(this);
+ }
+
+ public void setRenderer(GLSurfaceView.Renderer renderer) {
+ mRenderer = renderer;
+ }
+
+ public GLSurfaceView.Renderer getRenderer() {
+ return mRenderer;
+ }
+
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+ public synchronized void requestRender() {
+ if (mGLThread != null) {
+ mGLThread.renderFrame();
+ }
+ if (mListener != null) {
+ mListener.renderRequested();
+ }
+ }
+
+ /**
+ * Creates a Java GL thread. After this is called, the FlexibleGLSurfaceView may be used just
+ * like a GLSurfaceView. It is illegal to access the controller after this has been called.
+ */
+ public synchronized void createGLThread() {
+ if (mGLThread != null) {
+ throw new FlexibleGLSurfaceViewException("createGLThread() called with a GL thread " +
+ "already in place!");
+ }
+
+ Log.e(LOGTAG, "### Creating GL thread!");
+ mGLThread = new GLThread(mController);
+ mGLThread.start();
+ notifyAll();
+ }
+
+ /**
+ * Destroys the Java GL thread. Returns a Thread that completes when the Java GL thread is
+ * fully shut down.
+ */
+ public synchronized Thread destroyGLThread() {
+ // Wait for the GL thread to be started.
+ Log.e(LOGTAG, "### Waiting for GL thread to be created...");
+ while (mGLThread == null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ Log.e(LOGTAG, "### Destroying GL thread!");
+ Thread glThread = mGLThread;
+ mGLThread.shutdown();
+ mGLThread = null;
+ return glThread;
+ }
+
+ public synchronized void recreateSurface() {
+ if (mGLThread == null) {
+ throw new FlexibleGLSurfaceViewException("recreateSurface() called with no GL " +
+ "thread active!");
+ }
+
+ mGLThread.recreateSurface();
+ }
+
+ public synchronized GLController getGLController() {
+ if (mGLThread != null) {
+ throw new FlexibleGLSurfaceViewException("getGLController() called with a GL thread " +
+ "active; shut down the GL thread first!");
+ }
+
+ return mController;
+ }
+
+ public synchronized void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {
+ mController.sizeChanged(width, height);
+ if (mGLThread != null) {
+ mGLThread.surfaceChanged(width, height);
+ }
+
+ if (mListener != null) {
+ mListener.surfaceChanged(width, height);
+ }
+ }
+
+ public synchronized void surfaceCreated(SurfaceHolder holder) {
+ mController.surfaceCreated();
+ if (mGLThread != null) {
+ mGLThread.surfaceCreated();
+ }
+ }
+
+ public synchronized void surfaceDestroyed(SurfaceHolder holder) {
+ mController.surfaceDestroyed();
+ if (mGLThread != null) {
+ mGLThread.surfaceDestroyed();
+ }
+
+ if (mListener != null) {
+ mListener.compositionPauseRequested();
+ }
+ }
+
+ // Called from the compositor thread
+ public static GLController registerCxxCompositor() {
+ try {
+ Log.e(LOGTAG, "### registerCxxCompositor point A");
+ System.out.println("register layer comp");
+ Log.e(LOGTAG, "### registerCxxCompositor point B");
+ FlexibleGLSurfaceView flexView = (FlexibleGLSurfaceView) /*GeckoApp*/LibreOfficeMainActivity.mAppContext.getLayerController().getView();
+ Log.e(LOGTAG, "### registerCxxCompositor point C: " + flexView);
+ try {
+ flexView.destroyGLThread().join();
+ } catch (InterruptedException e) {}
+ Log.e(LOGTAG, "### registerCxxCompositor point D: " + flexView.getGLController());
+ return flexView.getGLController();
+ } catch (Exception e) {
+ Log.e(LOGTAG, "### Exception! " + e);
+ return null;
+ }
+ }
+
+ public interface Listener {
+ void renderRequested();
+ void compositionPauseRequested();
+ void compositionResumeRequested();
+ void surfaceChanged(int width, int height);
+ }
+
+ public static class FlexibleGLSurfaceViewException extends RuntimeException {
+ public static final long serialVersionUID = 1L;
+
+ FlexibleGLSurfaceViewException(String e) {
+ super(e);
+ }
+ }
+}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FloatSize.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FloatSize.java
index 21a712c..5fb73ec 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FloatSize.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/FloatSize.java
@@ -38,21 +38,32 @@
package org.mozilla.gecko.gfx;
-import org.mozilla.gecko.util.FloatUtils;
import org.json.JSONException;
import org.json.JSONObject;
+import org.mozilla.gecko.util.FloatUtils;
public class FloatSize {
public final float width, height;
- public FloatSize(FloatSize size) { width = size.width; height = size.height; }
- public FloatSize(IntSize size) { width = size.width; height = size.height; }
- public FloatSize(float aWidth, float aHeight) { width = aWidth; height = aHeight; }
+ public FloatSize(FloatSize size) {
+ width = size.width;
+ height = size.height;
+ }
+
+ public FloatSize(IntSize size) {
+ width = size.width;
+ height = size.height;
+ }
+
+ public FloatSize(float aWidth, float aHeight) {
+ width = aWidth;
+ height = aHeight;
+ }
public FloatSize(JSONObject json) {
try {
- width = (float)json.getDouble("width");
- height = (float)json.getDouble("height");
+ width = (float) json.getDouble("width");
+ height = (float) json.getDouble("height");
} catch (JSONException e) {
throw new RuntimeException(e);
}
@@ -82,7 +93,7 @@ public class FloatSize {
*/
public FloatSize interpolate(FloatSize to, float t) {
return new FloatSize(FloatUtils.interpolate(width, to.width, t),
- FloatUtils.interpolate(height, to.height, t));
+ FloatUtils.interpolate(height, to.height, t));
}
}
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLController.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLController.java
new file mode 100644
index 0000000..e8f2012
--- /dev/null
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLController.java
@@ -0,0 +1,279 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton at mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+package org.mozilla.gecko.gfx;
+
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGL11;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+import javax.microedition.khronos.opengles.GL;
+import javax.microedition.khronos.opengles.GL10;
+
+public class GLController {
+ private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ private static final String LOGTAG = "GeckoGLController";
+
+ private FlexibleGLSurfaceView mView;
+ private int mGLVersion;
+ private boolean mSurfaceValid;
+ private int mWidth, mHeight;
+
+ private EGL10 mEGL;
+ private EGLDisplay mEGLDisplay;
+ private EGLConfig mEGLConfig;
+ private EGLContext mEGLContext;
+ private EGLSurface mEGLSurface;
+
+ private GL mGL;
+
+ private static final int LOCAL_EGL_OPENGL_ES2_BIT = 4;
+
+ private static final int[] CONFIG_SPEC = {
+ EGL10.EGL_RED_SIZE, 5,
+ EGL10.EGL_GREEN_SIZE, 6,
+ EGL10.EGL_BLUE_SIZE, 5,
+ EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
+ EGL10.EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_NONE
+ };
+
+ public GLController(FlexibleGLSurfaceView view) {
+ mView = view;
+ mGLVersion = 2;
+ mSurfaceValid = false;
+ }
+
+ public void setGLVersion(int version) {
+ mGLVersion = version;
+ }
+
+ /** You must call this on the same thread you intend to use OpenGL on. */
+ public void initGLContext() {
+ initEGLContext();
+ createEGLSurface();
+ }
+
+ public void disposeGLContext() {
+ if (!mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
+ EGL10.EGL_NO_CONTEXT)) {
+ throw new GLControllerException("EGL context could not be released!");
+ }
+
+ if (mEGLSurface != null) {
+ if (!mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface)) {
+ throw new GLControllerException("EGL surface could not be destroyed!");
+ }
+
+ mEGLSurface = null;
+ }
+
+ if (mEGLContext == null) {
+ if (!mEGL.eglDestroyContext(mEGLDisplay, mEGLContext)) {
+ throw new GLControllerException("EGL context could not be destroyed!");
+ }
+
+ mGL = null;
+ mEGLDisplay = null;
+ mEGLConfig = null;
+ mEGLContext = null;
+ }
+ }
+
+ public GL getGL() { return mEGLContext.getGL(); }
+ public EGLDisplay getEGLDisplay() { return mEGLDisplay; }
+ public EGLConfig getEGLConfig() { return mEGLConfig; }
+ public EGLContext getEGLContext() { return mEGLContext; }
+ public EGLSurface getEGLSurface() { return mEGLSurface; }
+ public FlexibleGLSurfaceView getView() { return mView; }
+
+ public boolean hasSurface() {
+ return mEGLSurface != null;
+ }
+
+ public boolean swapBuffers() {
+ return mEGL.eglSwapBuffers(mEGLDisplay, mEGLSurface);
+ }
+
+ public boolean checkForLostContext() {
+ if (mEGL.eglGetError() != EGL11.EGL_CONTEXT_LOST) {
+ return false;
+ }
+
+ mEGLDisplay = null;
+ mEGLConfig = null;
+ mEGLContext = null;
+ mEGLSurface = null;
+ mGL = null;
+ return true;
+ }
+
+ public synchronized void waitForValidSurface() {
+ while (!mSurfaceValid) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public synchronized int getWidth() {
+ return mWidth;
+ }
+
+ public synchronized int getHeight() {
+ return mHeight;
+ }
+
+ synchronized void surfaceCreated() {
+ mSurfaceValid = true;
+ notifyAll();
+ }
+
+ synchronized void surfaceDestroyed() {
+ mSurfaceValid = false;
+ notifyAll();
+ }
+
+ synchronized void sizeChanged(int newWidth, int newHeight) {
+ mWidth = newWidth;
+ mHeight = newHeight;
+ }
+
+ private void initEGL() {
+ mEGL = (EGL10)EGLContext.getEGL();
+
+ mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {
+ throw new GLControllerException("eglGetDisplay() failed");
+ }
+
+ int[] version = new int[2];
+ if (!mEGL.eglInitialize(mEGLDisplay, version)) {
+ throw new GLControllerException("eglInitialize() failed");
+ }
+
+ mEGLConfig = chooseConfig();
+ }
+
+ private void initEGLContext() {
+ initEGL();
+
+ int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, mGLVersion, EGL10.EGL_NONE };
+ mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, EGL10.EGL_NO_CONTEXT,
+ attribList);
+ if (mEGLContext == null || mEGLContext == EGL10.EGL_NO_CONTEXT) {
+ throw new GLControllerException("createContext() failed");
+ }
+ }
+
+ private EGLConfig chooseConfig() {
+ int[] numConfigs = new int[1];
+ if (!mEGL.eglChooseConfig(mEGLDisplay, CONFIG_SPEC, null, 0, numConfigs) ||
+ numConfigs[0] <= 0) {
+ throw new GLControllerException("No available EGL configurations");
+ }
+
+ EGLConfig[] configs = new EGLConfig[numConfigs[0]];
+ if (!mEGL.eglChooseConfig(mEGLDisplay, CONFIG_SPEC, configs, numConfigs[0], numConfigs)) {
+ throw new GLControllerException("No EGL configuration for that specification");
+ }
+
+ // Select the first 565 RGB configuration.
+ int[] red = new int[1], green = new int[1], blue = new int[1];
+ for (EGLConfig config : configs) {
+ mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_RED_SIZE, red);
+ mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_GREEN_SIZE, green);
+ mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_BLUE_SIZE, blue);
+ if (red[0] == 5 && green[0] == 6 && blue[0] == 5) {
+ return config;
+ }
+ }
+
+ throw new GLControllerException("No suitable EGL configuration found");
+ }
+
+ private void createEGLSurface() {
+ SurfaceHolder surfaceHolder = mView.getHolder();
+ mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surfaceHolder, null);
+ if (mEGLSurface == null || mEGLSurface == EGL10.EGL_NO_SURFACE) {
+ throw new GLControllerException("EGL window surface could not be created!");
+ }
+
+ if (!mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
+ throw new GLControllerException("EGL surface could not be made into the current " +
+ "surface!");
+ }
+
+ mGL = mEGLContext.getGL();
+
+ if (mView.getRenderer() != null) {
+ mView.getRenderer().onSurfaceCreated((GL10)mGL, mEGLConfig);
+ mView.getRenderer().onSurfaceChanged((GL10)mGL, mView.getWidth(), mView.getHeight());
+ }
+ }
+
+ // Provides an EGLSurface without assuming ownership of this surface.
+ private EGLSurface provideEGLSurface() {
+ if (mEGL == null) {
+ initEGL();
+ }
+
+ SurfaceHolder surfaceHolder = mView.getHolder();
+ mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surfaceHolder, null);
+ if (mEGLSurface == null || mEGLSurface == EGL10.EGL_NO_SURFACE) {
+ throw new GLControllerException("EGL window surface could not be created!");
+ }
+
+ return mEGLSurface;
+ }
+
+ public static class GLControllerException extends RuntimeException {
+ public static final long serialVersionUID = 1L;
+
+ GLControllerException(String e) {
+ super(e);
+ }
+ }
+}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLThread.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLThread.java
new file mode 100644
index 0000000..4f788f6
--- /dev/null
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GLThread.java
@@ -0,0 +1,181 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton at mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+package org.mozilla.gecko.gfx;
+
+import android.opengl.GLSurfaceView;
+import android.view.SurfaceHolder;
+import javax.microedition.khronos.opengles.GL10;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+
+// A GL thread managed by Java. It is not necessary to use this class to use the
+// FlexibleGLSurfaceView, but it can be helpful, especially if the GL rendering is to be done
+// entirely in Java.
+class GLThread extends Thread {
+ private LinkedBlockingQueue<Runnable> mQueue;
+ private GLController mController;
+ private boolean mRenderQueued;
+
+ public GLThread(GLController controller) {
+ mQueue = new LinkedBlockingQueue<Runnable>();
+ mController = controller;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ Runnable runnable;
+ try {
+ runnable = mQueue.take();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ runnable.run();
+ if (runnable instanceof ShutdownMessage) {
+ break;
+ }
+ }
+ }
+
+ public void recreateSurface() {
+ mQueue.add(new RecreateSurfaceMessage());
+ }
+
+ public void renderFrame() {
+ // Make sure there's only one render event in the queue at a time.
+ synchronized (this) {
+ if (!mRenderQueued) {
+ mQueue.add(new RenderFrameMessage());
+ mRenderQueued = true;
+ }
+ }
+ }
+
+ public void shutdown() {
+ mQueue.add(new ShutdownMessage());
+ }
+
+ public void surfaceChanged(int width, int height) {
+ mQueue.add(new SizeChangedMessage(width, height));
+ }
+
+ public void surfaceCreated() {
+ mQueue.add(new SurfaceCreatedMessage());
+ }
+
+ public void surfaceDestroyed() {
+ mQueue.add(new SurfaceDestroyedMessage());
+ }
+
+ private void doRecreateSurface() {
+ mController.disposeGLContext();
+ mController.initGLContext();
+ }
+
+ private GLSurfaceView.Renderer getRenderer() {
+ return mController.getView().getRenderer();
+ }
+
+ private class RecreateSurfaceMessage implements Runnable {
+ public void run() {
+ doRecreateSurface();
+ }
+ }
+
+ private class RenderFrameMessage implements Runnable {
+ public void run() {
+ synchronized (GLThread.this) {
+ mRenderQueued = false;
+ }
+
+ // Bail out if the surface was lost.
+ if (mController.getEGLSurface() == null) {
+ return;
+ }
+
+ GLSurfaceView.Renderer renderer = getRenderer();
+ if (renderer != null) {
+ renderer.onDrawFrame((GL10)mController.getGL());
+ }
+
+ mController.swapBuffers();
+ //if (!mController.swapBuffers() && mController.checkForLostContext()) {
+ // doRecreateSurface();
+ //}
+ }
+ }
+
+ private class ShutdownMessage implements Runnable {
+ public void run() {
+ mController.disposeGLContext();
+ mController = null;
+ }
+ }
+
+ private class SizeChangedMessage implements Runnable {
+ private int mWidth, mHeight;
+
+ public SizeChangedMessage(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ public void run() {
+ GLSurfaceView.Renderer renderer = getRenderer();
+ if (renderer != null) {
+ renderer.onSurfaceChanged((GL10)mController.getGL(), mWidth, mHeight);
+ }
+ }
+ }
+
+ private class SurfaceCreatedMessage implements Runnable {
+ public void run() {
+ if (!mController.hasSurface()) {
+ mController.initGLContext();
+ }
+ }
+ }
+
+ private class SurfaceDestroyedMessage implements Runnable {
+ public void run() {
+ mController.disposeGLContext();
+ }
+ }
+}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoGLLayerClient.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoGLLayerClient.java
new file mode 100644
index 0000000..9e4f376
--- /dev/null
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoGLLayerClient.java
@@ -0,0 +1,265 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton at mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+package org.mozilla.gecko.gfx;
+
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.View;
+
+import org.libreoffice.LOEvent;
+import org.libreoffice.LOKitShell;
+
+public class GeckoGLLayerClient extends GeckoLayerClient
+ implements FlexibleGLSurfaceView.Listener, VirtualLayer.Listener {
+ private static final String LOGTAG = "GeckoGLLayerClient";
+
+ private LayerRenderer mLayerRenderer;
+ private boolean mLayerRendererInitialized;
+
+ public GeckoGLLayerClient(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Rect beginDrawing(int width, int height, int tileWidth, int tileHeight,
+ String metadata, boolean hasDirectTexture) {
+ Rect bufferRect = super.beginDrawing(width, height, tileWidth, tileHeight,
+ metadata, hasDirectTexture);
+ if (bufferRect == null) {
+ return null;
+ }
+
+ // Be sure to adjust the buffer size; if it's not at least as large as the viewport size,
+ // ViewportMetrics.getOptimumViewportOffset() gets awfully confused and severe display
+ // corruption results!
+ if (mBufferSize.width != width || mBufferSize.height != height) {
+ mBufferSize = new IntSize(width, height);
+ }
+
+ return bufferRect;
+ }
+
+ @Override
+ protected boolean handleDirectTextureChange(boolean hasDirectTexture) {
+ Log.e(LOGTAG, "### handleDirectTextureChange");
+ if (mTileLayer != null) {
+ return false;
+ }
+
+ Log.e(LOGTAG, "### Creating virtual layer");
+ VirtualLayer virtualLayer = new VirtualLayer();
+ virtualLayer.setListener(this);
+ virtualLayer.setSize(getBufferSize());
+ getLayerController().setRoot(virtualLayer);
+ mTileLayer = virtualLayer;
+
+ sendResizeEventIfNecessary(true);
+ return true;
+ }
+
+ @Override
+ public void setLayerController(LayerController layerController) {
+ super.setLayerController(layerController);
+
+ LayerView view = layerController.getView();
+ view.setListener(this);
+
+ mLayerRenderer = new LayerRenderer(view);
+ }
+
+ @Override
+ protected boolean shouldDrawProceed(int tileWidth, int tileHeight) {
+ Log.e(LOGTAG, "### shouldDrawProceed");
+ // Always draw.
+ return true;
+ }
+
+ @Override
+ protected void updateLayerAfterDraw(Rect updatedRect) {
+ Log.e(LOGTAG, "### updateLayerAfterDraw");
+ // Nothing to do.
+ }
+
+ @Override
+ protected IntSize getBufferSize() {
+ View view = (View) getLayerController().getView();
+ IntSize size = new IntSize(view.getWidth(), view.getHeight());
+ Log.e(LOGTAG, "### getBufferSize " + size);
+ return size;
+ }
+
+ @Override
+ protected IntSize getTileSize() {
+ Log.e(LOGTAG, "### getTileSize " + getBufferSize());
+ return getBufferSize();
+ }
+
+ @Override
+ protected void tileLayerUpdated() {
+ // Set the new origin and resolution instantly.
+ mTileLayer.performUpdates(null);
+ }
+
+ @Override
+ public Bitmap getBitmap() {
+ Log.e(LOGTAG, "### getBitmap");
+ IntSize size = getBufferSize();
+ try {
+ return Bitmap.createBitmap(size.width, size.height, Bitmap.Config.RGB_565);
+ } catch (OutOfMemoryError oom) {
+ Log.e(LOGTAG, "Unable to create bitmap", oom);
+ return null;
+ }
+ }
+
+ @Override
+ public int getType() {
+ Log.e(LOGTAG, "### getType");
+ return LAYER_CLIENT_TYPE_GL;
+ }
+
+ public void dimensionsChanged(Point newOrigin, float newResolution) {
+ Log.e(LOGTAG, "### dimensionsChanged " + newOrigin + " " + newResolution);
+ }
+
+ /* Informs Gecko that the screen size has changed. */
+ @Override
+ protected void sendResizeEventIfNecessary(boolean force) {
+ Log.e(LOGTAG, "### sendResizeEventIfNecessary " + force);
+
+ IntSize newSize = getBufferSize();
+ if (!force && mScreenSize != null && mScreenSize.equals(newSize)) {
+ return;
+ }
+
+ mScreenSize = newSize;
+
+ Log.e(LOGTAG, "### Screen-size changed to " + mScreenSize);
+ //GeckoEvent event = GeckoEvent.createSizeChangedEvent(mScreenSize.width, mScreenSize.height,
+ // mScreenSize.width, mScreenSize.height,
+ // mScreenSize.width, mScreenSize.height);
+ //GeckoAppShell.sendEventToGecko(event);
+ LOEvent event = LOEvent.sizeChanged(mScreenSize.width, mScreenSize.height,
+ mScreenSize.width, mScreenSize.height,
+ mScreenSize.width, mScreenSize.height);
+ LOKitShell.sendEvent(event);
+
+ }
+
+ /**
+ * For Gecko to use.
+ */
+ public ViewTransform getViewTransform() {
+ Log.e(LOGTAG, "### getViewTransform()");
+
+ // NB: We don't begin a transaction here because this can be called in a synchronous
+ // manner between beginDrawing() and endDrawing(), and that will cause a deadlock.
+
+ LayerController layerController = getLayerController();
+ synchronized (layerController) {
+ ViewportMetrics viewportMetrics = layerController.getViewportMetrics();
+ PointF viewportOrigin = viewportMetrics.getOrigin();
+ Point tileOrigin = mTileLayer.getOrigin();
+ float scrollX = viewportOrigin.x;
+ float scrollY = viewportOrigin.y;
+ float zoomFactor = viewportMetrics.getZoomFactor();
+ Log.e(LOGTAG, "### Viewport metrics = " + viewportMetrics + " tile reso = " +
+ mTileLayer.getResolution());
+ return new ViewTransform(scrollX, scrollY, zoomFactor);
+ }
+ }
+
+ public void renderRequested() {
+ Log.e(LOGTAG, "### Render requested, scheduling composite");
+ LOKitShell.scheduleComposite();
+ }
+
+ public void compositionPauseRequested() {
+ Log.e(LOGTAG, "### Scheduling PauseComposition");
+ LOKitShell.schedulePauseComposition();
+ }
+
+ public void compositionResumeRequested() {
+ Log.e(LOGTAG, "### Scheduling ResumeComposition");
+ LOKitShell.scheduleResumeComposition();
+ }
+
+ public void surfaceChanged(int width, int height) {
+ compositionPauseRequested();
+ LayerController layerController = getLayerController();
+ layerController.setViewportSize(new FloatSize(width, height));
+ compositionResumeRequested();
+ renderRequested();
+ }
+
+ /**
+ * For Gecko to use.
+ */
+ public LayerRenderer.Frame createFrame() {
+ // Create the shaders and textures if necessary.
+ if (!mLayerRendererInitialized) {
+ mLayerRenderer.createProgram();
+ mLayerRendererInitialized = true;
+ }
+
+ // Build the contexts and create the frame.
+ Layer.RenderContext pageContext = mLayerRenderer.createPageContext();
+ Layer.RenderContext screenContext = mLayerRenderer.createScreenContext();
+ return mLayerRenderer.createFrame(pageContext, screenContext);
+ }
+
+ /**
+ * For Gecko to use.
+ */
+ public void activateProgram() {
+ mLayerRenderer.activateProgram();
+ }
+
+ /**
+ * For Gecko to use.
+ */
+ public void deactivateProgram() {
+ mLayerRenderer.deactivateProgram();
+ }
+}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
new file mode 100644
index 0000000..09349b4
--- /dev/null
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -0,0 +1,414 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Patrick Walton <pcwalton at mozilla.com>
+ * Chris Lord <chrislord.net at gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * 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 ***** */
+
+package org.mozilla.gecko.gfx;
+
+import org.libreoffice.LOEvent;
+import org.libreoffice.LOKitShell;
+import org.libreoffice.LibreOfficeMainActivity;
+import org.mozilla.gecko.util.FloatUtils;
+//import org.mozilla.gecko.GeckoApp;
+//import org.mozilla.gecko.GeckoAppShell;
+//import org.mozilla.gecko.GeckoEvent;
+import org.mozilla.gecko.GeckoEventListener;
+import org.json.JSONException;
+import org.json.JSONObject;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public abstract class GeckoLayerClient extends LayerClient implements GeckoEventListener {
+ private static final String LOGTAG = "GeckoLayerClient";
+
+ public static final int LAYER_CLIENT_TYPE_NONE = 0;
+ public static final int LAYER_CLIENT_TYPE_SOFTWARE = 1;
+ public static final int LAYER_CLIENT_TYPE_GL = 2;
+
+ protected IntSize mScreenSize;
+ protected IntSize mBufferSize;
+
+ protected Layer mTileLayer;
+
+ /* The viewport that Gecko is currently displaying. */
+ protected ViewportMetrics mGeckoViewport;
+
+ /* The viewport that Gecko will display when drawing is finished */
+ protected ViewportMetrics mNewGeckoViewport;
+
+ private static final long MIN_VIEWPORT_CHANGE_DELAY = 25L;
+ private long mLastViewportChangeTime;
+ private boolean mPendingViewportAdjust;
+ private boolean mViewportSizeChanged;
+
+ // mUpdateViewportOnEndDraw is used to indicate that we received a
+ // viewport update notification while drawing. therefore, when the
+ // draw finishes, we need to update the entire viewport rather than
+ // just the page size. this boolean should always be accessed from
+ // inside a transaction, so no synchronization is needed.
+ private boolean mUpdateViewportOnEndDraw;
+
+ private String mLastCheckerboardColor;
+
+ private static Pattern sColorPattern;
+
+ /* Used by robocop for testing purposes */
+ private DrawListener mDrawListener;
+
+ protected abstract boolean handleDirectTextureChange(boolean hasDirectTexture);
+ protected abstract boolean shouldDrawProceed(int tileWidth, int tileHeight);
+ protected abstract void updateLayerAfterDraw(Rect updatedRect);
+ protected abstract IntSize getBufferSize();
+ protected abstract IntSize getTileSize();
+ protected abstract void tileLayerUpdated();
+ public abstract Bitmap getBitmap();
+ public abstract int getType();
+
+ public GeckoLayerClient(Context context) {
+ mScreenSize = new IntSize(0, 0);
+ mBufferSize = new IntSize(0, 0);
+ }
+
+ /** Attaches the root layer to the layer controller so that Gecko appears. */
+ @Override
+ public void setLayerController(LayerController layerController) {
+ super.setLayerController(layerController);
+
+ layerController.setRoot(mTileLayer);
+ if (mGeckoViewport != null) {
+ layerController.setViewportMetrics(mGeckoViewport);
+ }
+
+ //GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this);
+ //GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
+
+ sendResizeEventIfNecessary();
+ }
+
+ public Rect beginDrawing(int width, int height, int tileWidth, int tileHeight,
+ String metadata, boolean hasDirectTexture) {
+ Log.e(LOGTAG, "### beginDrawing " + width + " " + height + " " + tileWidth + " " +
+ tileHeight + " " + hasDirectTexture);
+
+ // If we've changed surface types, cancel this draw
+ if (handleDirectTextureChange(hasDirectTexture)) {
+ Log.e(LOGTAG, "### Cancelling draw due to direct texture change");
+ return null;
+ }
+
+ if (!shouldDrawProceed(tileWidth, tileHeight)) {
+ Log.e(LOGTAG, "### Cancelling draw due to shouldDrawProceed()");
+ return null;
+ }
+
+ LayerController controller = getLayerController();
+
+ try {
+ JSONObject viewportObject = new JSONObject(metadata);
+ mNewGeckoViewport = new ViewportMetrics(viewportObject);
+
+ Log.e(LOGTAG, "### beginDrawing new Gecko viewport " + mNewGeckoViewport);
+
+ // Update the background color, if it's present.
+ String backgroundColorString = viewportObject.optString("backgroundColor");
+ if (backgroundColorString != null && !backgroundColorString.equals(mLastCheckerboardColor)) {
+ mLastCheckerboardColor = backgroundColorString;
+ controller.setCheckerboardColor(parseColorFromGecko(backgroundColorString));
+ }
+ } catch (JSONException e) {
+ Log.e(LOGTAG, "Aborting draw, bad viewport description: " + metadata);
+ return null;
+ }
+
+
+ // Make sure we don't spend time painting areas we aren't interested in.
+ // Only do this if the Gecko viewport isn't going to override our viewport.
+ Rect bufferRect = new Rect(0, 0, width, height);
+
+ if (!mUpdateViewportOnEndDraw) {
+ // First, find out our ideal displayport. We do this by taking the
+ // clamped viewport origin and taking away the optimum viewport offset.
+ // This would be what we would send to Gecko if adjustViewport were
+ // called now.
+ ViewportMetrics currentMetrics = controller.getViewportMetrics();
+ PointF currentBestOrigin = RectUtils.getOrigin(currentMetrics.getClampedViewport());
+ PointF viewportOffset = currentMetrics.getOptimumViewportOffset(new IntSize(width, height));
+ currentBestOrigin.offset(-viewportOffset.x, -viewportOffset.y);
+
+ Rect currentRect = RectUtils.round(new RectF(currentBestOrigin.x, currentBestOrigin.y,
+ currentBestOrigin.x + width, currentBestOrigin.y + height));
+
+ // Second, store Gecko's displayport.
+ PointF currentOrigin = mNewGeckoViewport.getDisplayportOrigin();
+ bufferRect = RectUtils.round(new RectF(currentOrigin.x, currentOrigin.y,
+ currentOrigin.x + width, currentOrigin.y + height));
+
+
+ // Take the intersection of the two as the area we're interested in rendering.
+ if (!bufferRect.intersect(currentRect)) {
+ // If there's no intersection, we have no need to render anything,
+ // but make sure to update the viewport size.
+ beginTransaction(mTileLayer);
+ try {
+ updateViewport(true);
+ } finally {
+ endTransaction(mTileLayer);
+ }
+ return null;
+ }
+ bufferRect.offset(Math.round(-currentOrigin.x), Math.round(-currentOrigin.y));
+ }
+
+ beginTransaction(mTileLayer);
+ return bufferRect;
+ }
+
+ /*
+ * TODO: Would be cleaner if this took an android.graphics.Rect instead, but that would require
+ * a little more JNI magic.
+ */
+ public void endDrawing(int x, int y, int width, int height) {
+ synchronized (getLayerController()) {
+ try {
+ updateViewport(!mUpdateViewportOnEndDraw);
+ mUpdateViewportOnEndDraw = false;
+
+ Rect rect = new Rect(x, y, x + width, y + height);
+ updateLayerAfterDraw(rect);
+ } finally {
+ endTransaction(mTileLayer);
+ }
+ }
+ Log.i(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - endDrawing");
+
+ /* Used by robocop for testing purposes */
+ if (mDrawListener != null) {
+ mDrawListener.drawFinished(x, y, width, height);
+ }
+ }
+
+ protected void updateViewport(boolean onlyUpdatePageSize) {
+ // save and restore the viewport size stored in java; never let the
+ // JS-side viewport dimensions override the java-side ones because
+ // java is the One True Source of this information, and allowing JS
+ // to override can lead to race conditions where this data gets clobbered.
+ FloatSize viewportSize = getLayerController().getViewportSize();
+ mGeckoViewport = mNewGeckoViewport;
+ mGeckoViewport.setSize(viewportSize);
+
+ LayerController controller = getLayerController();
+ PointF displayportOrigin = mGeckoViewport.getDisplayportOrigin();
+ mTileLayer.setOrigin(PointUtils.round(displayportOrigin));
+ mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
+
+ this.tileLayerUpdated();
+ Log.e(LOGTAG, "### updateViewport onlyUpdatePageSize=" + onlyUpdatePageSize +
+ " getTileViewport " + mGeckoViewport);
+
+ if (onlyUpdatePageSize) {
+ // Don't adjust page size when zooming unless zoom levels are
+ // approximately equal.
+ if (FloatUtils.fuzzyEquals(controller.getZoomFactor(),
+ mGeckoViewport.getZoomFactor()))
+ controller.setPageSize(mGeckoViewport.getPageSize());
+ } else {
+ controller.setViewportMetrics(mGeckoViewport);
+ controller.abortPanZoomAnimation();
+ }
+ }
+
+ /* Informs Gecko that the screen size has changed. */
+ protected void sendResizeEventIfNecessary(boolean force) {
+ Log.e(LOGTAG, "### sendResizeEventIfNecessary " + force);
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ /*GeckoApp*/LibreOfficeMainActivity.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ // Return immediately if the screen size hasn't changed or the viewport
+ // size is zero (which indicates that the rendering surface hasn't been
+ // allocated yet).
+ boolean screenSizeChanged = (metrics.widthPixels != mScreenSize.width ||
+ metrics.heightPixels != mScreenSize.height);
+ boolean viewportSizeValid = (getLayerController() != null &&
+ getLayerController().getViewportSize().isPositive());
+ if (!(force || (screenSizeChanged && viewportSizeValid))) {
+ return;
+ }
+
+ mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
+ IntSize bufferSize = getBufferSize(), tileSize = getTileSize();
+
+ Log.e(LOGTAG, "### Screen-size changed to " + mScreenSize);
+ //GeckoEvent event = GeckoEvent.createSizeChangedEvent(bufferSize.width, bufferSize.height,
+ // metrics.widthPixels, metrics.heightPixels,
+ // tileSize.width, tileSize.height);
+ //GeckoAppShell.sendEventToGecko(event);
+ LOEvent event = LOEvent.sizeChanged(bufferSize.width, bufferSize.height,
+ metrics.widthPixels, metrics.heightPixels,
+ tileSize.width, tileSize.height);
+ }
+
+ // Parses a color from an RGB triple of the form "rgb([0-9]+, [0-9]+, [0-9]+)". If the color
+ // cannot be parsed, returns white.
+ private static int parseColorFromGecko(String string) {
+ if (sColorPattern == null) {
+ sColorPattern = Pattern.compile("rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)");
+ }
+
+ Matcher matcher = sColorPattern.matcher(string);
+ if (!matcher.matches()) {
+ return Color.WHITE;
+ }
+
+ int r = Integer.parseInt(matcher.group(1));
+ int g = Integer.parseInt(matcher.group(2));
+ int b = Integer.parseInt(matcher.group(3));
+ return Color.rgb(r, g, b);
+ }
+
+ @Override
+ public void render() {
+ adjustViewportWithThrottling();
+ }
+
+ private void adjustViewportWithThrottling() {
+ if (!getLayerController().getRedrawHint())
+ return;
+
+ if (mPendingViewportAdjust)
+ return;
+
+ long timeDelta = System.currentTimeMillis() - mLastViewportChangeTime;
+ if (timeDelta < MIN_VIEWPORT_CHANGE_DELAY) {
+ getLayerController().getView().postDelayed(
+ new Runnable() {
+ public void run() {
+ mPendingViewportAdjust = false;
+ adjustViewport();
+ }
+ }, MIN_VIEWPORT_CHANGE_DELAY - timeDelta);
+ mPendingViewportAdjust = true;
+ return;
+ }
+
+ adjustViewport();
+ }
+
+ @Override
+ public void viewportSizeChanged() {
+ mViewportSizeChanged = true;
+ }
+
+ private void adjustViewport() {
+ ViewportMetrics viewportMetrics =
+ new ViewportMetrics(getLayerController().getViewportMetrics());
+
+ PointF viewportOffset = viewportMetrics.getOptimumViewportOffset(mBufferSize);
+ viewportMetrics.setViewportOffset(viewportOffset);
+ viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
+
+ //GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(viewportMetrics));
+ LOKitShell.sendEvent(LOEvent.viewport(viewportMetrics));
+ if (mViewportSizeChanged) {
+ mViewportSizeChanged = false;
+ //GeckoAppShell.viewSizeChanged();
+ LOKitShell.viewSizeChanged();
+ }
+
+ mLastViewportChangeTime = System.currentTimeMillis();
+ }
+
+ public void handleMessage(String event, JSONObject message) {
+ if ("Viewport:UpdateAndDraw".equals(event)) {
+ Log.e(LOGTAG, "### Java side Viewport:UpdateAndDraw()!");
+ mUpdateViewportOnEndDraw = true;
+
+ // Redraw everything.
+ Rect rect = new Rect(0, 0, mBufferSize.width, mBufferSize.height);
+ //GeckoAppShell.sendEventToGecko(GeckoEvent.createDrawEvent(rect));
+ LOKitShell.sendEvent(LOEvent.draw(rect));
+ } else if ("Viewport:UpdateLater".equals(event)) {
+ Log.e(LOGTAG, "### Java side Viewport:UpdateLater()!");
+ mUpdateViewportOnEndDraw = true;
+ }
+ }
+
+ @Override
+ public void geometryChanged() {
+ /* Let Gecko know if the screensize has changed */
+ sendResizeEventIfNecessary();
+ render();
+ }
+
+ public int getWidth() {
+ return mBufferSize.width;
+ }
+
+ public int getHeight() {
+ return mBufferSize.height;
+ }
+
+ public ViewportMetrics getGeckoViewportMetrics() {
+ // Return a copy, as we modify this inside the Gecko thread
+ if (mGeckoViewport != null)
+ return new ViewportMetrics(mGeckoViewport);
+ return null;
+ }
+
+ private void sendResizeEventIfNecessary() {
+ sendResizeEventIfNecessary(false);
+ }
+
+ /** Used by robocop for testing purposes. Not for production use! This is called via reflection by robocop. */
+ public void setDrawListener(DrawListener listener) {
+ mDrawListener = listener;
+ }
+
+ /** Used by robocop for testing purposes. Not for production use! This is used via reflection by robocop. */
+ public interface DrawListener {
+ public void drawFinished(int x, int y, int width, int height);
+ }
+}
+
diff --git a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
index 9385d81..97cbfb4 100644
--- a/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
+++ b/android/experimental/LOAndroid2/app/src/main/java/org/mozilla/gecko/gfx/GeckoSoftwareLayerClient.java
@@ -38,130 +38,70 @@
package org.mozilla.gecko.gfx;
+import org.libreoffice.LOKitShell;
+import org.mozilla.gecko.gfx.CairoImage;
+import org.mozilla.gecko.gfx.IntSize;
+import org.mozilla.gecko.gfx.LayerClient;
+import org.mozilla.gecko.gfx.LayerController;
+import org.mozilla.gecko.gfx.LayerRenderer;
+import org.mozilla.gecko.gfx.MultiTileLayer;
+import org.mozilla.gecko.gfx.PointUtils;
+import org.mozilla.gecko.gfx.WidgetTileLayer;
+//import org.mozilla.gecko.GeckoAppShell;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.PointF;
+import android.graphics.Point;
import android.graphics.Rect;
-import android.util.DisplayMetrics;
+import android.graphics.RectF;
import android.util.Log;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.libreoffice.LOEvent;
-import org.libreoffice.LOKitShell;
-import org.libreoffice.LibreOfficeMainActivity;
-import org.mozilla.gecko.GeckoEventListener;
-import org.mozilla.gecko.util.FloatUtils;
-
import java.nio.ByteBuffer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-//import org.mozilla.gecko.GeckoApp;
-//import org.mozilla.gecko.GeckoAppShell;
-//import org.mozilla.gecko.GeckoEvent;
/**
* Transfers a software-rendered Gecko to an ImageLayer so that it can be rendered by our
* compositor.
- * <p/>
+ *
* TODO: Throttle down Gecko's priority when we pan and zoom.
*/
-public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventListener {
+public class GeckoSoftwareLayerClient extends GeckoLayerClient {
private static final String LOGTAG = "GeckoSoftwareLayerClient";
- private static final IntSize TILE_SIZE = new IntSize(256, 256);
- private static final long MIN_VIEWPORT_CHANGE_DELAY = 350L;
- private static Pattern sColorPattern;
- private Context mContext;
+
private int mFormat;
- private IntSize mScreenSize;
- private IntSize mBufferSize;
+ private IntSize mViewportSize;
private ByteBuffer mBuffer;
- private Layer mTileLayer;
- /* The viewport rect that Gecko is currently displaying. */
- private ViewportMetrics mGeckoViewport;
+
private CairoImage mCairoImage;
- private long mLastViewportChangeTime;
- private boolean mPendingViewportAdjust;
- private boolean mViewportSizeChanged;
+
+ private static final IntSize TILE_SIZE = new IntSize(256, 256);
+
// Whether or not the last paint we got used direct texturing
private boolean mHasDirectTexture;
- // mUpdateViewportOnEndDraw is used to indicate that we received a
- // viewport update notification while drawing. therefore, when the
- // draw finishes, we need to update the entire viewport rather than
- // just the page size. this boolean should always be accessed from
- // inside a transaction, so no synchronization is needed.
- private boolean mUpdateViewportOnEndDraw;
public GeckoSoftwareLayerClient(Context context) {
- mContext = context;
+ super(context);
- mScreenSize = new IntSize(0, 0);
- mBufferSize = new IntSize(0, 0);
mFormat = CairoImage.FORMAT_RGB16_565;
mCairoImage = new CairoImage() {
@Override
- public ByteBuffer getBuffer() {
- return mBuffer;
- }
-
+ public ByteBuffer getBuffer() { return mBuffer; }
@Override
- public IntSize getSize() {
- return mBufferSize;
- }
-
+ public IntSize getSize() { return mBufferSize; }
@Override
- public int getFormat() {
- return mFormat;
- }
+ public int getFormat() { return mFormat; }
};
-
- mTileLayer = new MultiTileLayer(mCairoImage, TILE_SIZE);
- }
-
- // Parses a color from an RGB triple of the form "rgb([0-9]+, [0-9]+, [0-9]+)". If the color
- // cannot be parsed, returns white.
- private static int parseColorFromGecko(String string) {
- if (sColorPattern == null) {
- sColorPattern = Pattern.compile("rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)");
- }
-
- Matcher matcher = sColorPattern.matcher(string);
- if (!matcher.matches()) {
- return Color.WHITE;
- }
-
- int r = Integer.parseInt(matcher.group(1));
- int g = Integer.parseInt(matcher.group(2));
- int b = Integer.parseInt(matcher.group(3));
- return Color.rgb(r, g, b);
- }
-
- public int getWidth() {
- return mBufferSize.width;
- }
-
- public int getHeight() {
- return mBufferSize.height;
}
protected void finalize() throws Throwable {
try {
if (mBuffer != null)
- /*GeckoAppShell*/ LOKitShell.freeDirectBuffer(mBuffer);
+ LOKitShell.freeDirectBuffer(mBuffer);
mBuffer = null;
} finally {
super.finalize();
}
}
- /**
- * Attaches the root layer to the layer controller so that Gecko appears.
- */
- @Override
public void setLayerController(LayerController layerController) {
super.setLayerController(layerController);
@@ -172,142 +112,100 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
//GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this);
//GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
+ //GeckoAppShell.registerGeckoEventListener("Checkerboard:Toggle", this);
- // This needs to happen before a call to sendResizeEventIfNecessary
- // happens, but only needs to be called once. As that is only called by
- // the layer controller or this, here is a safe place to do so.
- if (mTileLayer instanceof MultiTileLayer) {
- //GeckoEvent event = new GeckoEvent(GeckoEvent.TILE_SIZE, TILE_SIZE);
- //GeckoAppShell.sendEventToGecko(event);
- LOKitShell.sendEvent(LOEvent.tileSize(TILE_SIZE));
- }
-
- sendResizeEventIfNecessary();
+ // XXX: Review pcwalton. This signature changed on m-c, should force = false here?
+ sendResizeEventIfNecessary(false);
}
- private void setHasDirectTexture(boolean hasDirectTexture) {
- if (hasDirectTexture == mHasDirectTexture)
- return;
+ @Override
+ protected boolean handleDirectTextureChange(boolean hasDirectTexture) {
+ if (mTileLayer != null && hasDirectTexture == mHasDirectTexture)
+ return false;
mHasDirectTexture = hasDirectTexture;
- IntSize tileSize;
if (mHasDirectTexture) {
+ Log.i(LOGTAG, "Creating WidgetTileLayer");
mTileLayer = new WidgetTileLayer(mCairoImage);
- tileSize = new IntSize(0, 0);
} else {
+ Log.i(LOGTAG, "Creating MultiTileLayer");
mTileLayer = new MultiTileLayer(mCairoImage, TILE_SIZE);
- tileSize = TILE_SIZE;
}
getLayerController().setRoot(mTileLayer);
- //GeckoEvent event = new GeckoEvent(GeckoEvent.TILE_SIZE, tileSize);
- //GeckoAppShell.sendEventToGecko(event);
- LOKitShell.sendEvent(LOEvent.tileSize(tileSize));
-
// Force a resize event to be sent because the results of this
// are different depending on what tile system we're using
sendResizeEventIfNecessary(true);
- }
-
- public void beginDrawing(int width, int height) {
- beginTransaction(mTileLayer);
-
- if (mBufferSize.width != width || mBufferSize.height != height) {
- mBufferSize = new IntSize(width, height);
-
- // Reallocate the buffer if necessary
- // * 2 because it's a 16-bit buffer (so 2 bytes per pixel).
- int size = mBufferSize.getArea() * 2;
- if (mBuffer == null || mBuffer.capacity() != size) {
- // Free the old buffer
- if (mBuffer != null) {
- /*GeckoAppShell*/
- LOKitShell.freeDirectBuffer(mBuffer);
- mBuffer = null;
- }
-
- mBuffer = /*GeckoAppShell*/LOKitShell.allocateDirectBuffer(size);
- }
- }
+ return true;
}
- private void updateViewport(String viewportDescription, final boolean onlyUpdatePageSize) {
- try {
- JSONObject viewportObject = new JSONObject(viewportDescription);
-
- // save and restore the viewport size stored in java; never let the
- // JS-side viewport dimensions override the java-side ones because
- // java is the One True Source of this information, and allowing JS
- // to override can lead to race conditions where this data gets clobbered.
- FloatSize viewportSize = getLayerController().getViewportSize();
- mGeckoViewport = new ViewportMetrics(viewportObject);
- mGeckoViewport.setSize(viewportSize);
-
- LayerController controller = getLayerController();
- PointF displayportOrigin = mGeckoViewport.getDisplayportOrigin();
- mTileLayer.setOrigin(PointUtils.round(displayportOrigin));
- mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
-
- if (onlyUpdatePageSize) {
- // Don't adjust page size when zooming unless zoom levels are
- // approximately equal.
- if (FloatUtils.fuzzyEquals(controller.getZoomFactor(),
- mGeckoViewport.getZoomFactor()))
- controller.setPageSize(mGeckoViewport.getPageSize());
- } else {
- Log.d(LOGTAG, "Received viewport update from gecko");
- controller.setViewportMetrics(mGeckoViewport);
- controller.abortPanZoomAnimation();
+ @Override
+ protected boolean shouldDrawProceed(int tileWidth, int tileHeight) {
+ // Make sure the tile-size matches. If it doesn't, we could crash trying
+ // to access invalid memory.
+ if (mHasDirectTexture) {
+ if (tileWidth != 0 || tileHeight != 0) {
+ Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" +
+ tileHeight);
+ return false;
}
-
- // Update the background color, if it's present.
- String backgroundColorString = viewportObject.optString("backgroundColor");
- if (backgroundColorString != null) {
- controller.setCheckerboardColor(parseColorFromGecko(backgroundColorString));
+ } else {
+ if (tileWidth != TILE_SIZE.width || tileHeight != TILE_SIZE.height) {
+ Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" +
+ tileHeight);
+ return false;
}
- } catch (JSONException e) {
- Log.e(LOGTAG, "Bad viewport description: " + viewportDescription);
- throw new RuntimeException(e);
}
- }
- public ByteBuffer getBuffer() {
- return mBuffer;
+ return true;
}
- /*
- * TODO: Would be cleaner if this took an android.graphics.Rect instead, but that would require
- * a little more JNI magic.
- */
- public void endDrawing(int x, int y, int width, int height, String metadata, boolean hasDirectTexture) {
- synchronized (getLayerController()) {
- try {
- updateViewport(metadata, !mUpdateViewportOnEndDraw);
- mUpdateViewportOnEndDraw = false;
- Rect rect = new Rect(x, y, x + width, y + height);
+ @Override
+ public Rect beginDrawing(int width, int height, int tileWidth, int tileHeight,
+ String metadata, boolean hasDirectTexture) {
+ Rect bufferRect = super.beginDrawing(width, height, tileWidth, tileHeight,
+ metadata, hasDirectTexture);
+ if (bufferRect == null) {
+ return bufferRect;
+ }
- setHasDirectTexture(hasDirectTexture);
+ // If the window size has changed, reallocate the buffer to match.
+ if (mBufferSize.width != width || mBufferSize.height != height) {
+ mBufferSize = new IntSize(width, height);
- if (!mHasDirectTexture)
- ((MultiTileLayer) mTileLayer).invalidate(rect);
- } finally {
- endTransaction(mTileLayer);
+ // Reallocate the buffer if necessary
+ if (mTileLayer instanceof MultiTileLayer) {
+ int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
+ int size = mBufferSize.getArea() * bpp;
+ if (mBuffer == null || mBuffer.capacity() != size) {
+ // Free the old buffer
+ if (mBuffer != null) {
+ LOKitShell.freeDirectBuffer(mBuffer);
+ mBuffer = null;
+ }
+
+ mBuffer = LOKitShell.allocateDirectBuffer(size);
+ }
}
}
+
+ return bufferRect;
}
- public ViewportMetrics getGeckoViewportMetrics() {
- // Return a copy, as we modify this inside the Gecko thread
- if (mGeckoViewport != null)
- return new ViewportMetrics(mGeckoViewport);
- return null;
+ @Override
+ protected void updateLayerAfterDraw(Rect updatedRect) {
+ if (!(mTileLayer instanceof MultiTileLayer)) {
+ return;
+ }
+
+ ((MultiTileLayer)mTileLayer).invalidate(updatedRect);
}
- public void copyPixelsFromMultiTileLayer(Bitmap target) {
- Canvas canvas = new Canvas(target);
+ private void copyPixelsFromMultiTileLayer(Bitmap target) {
+ Canvas c = new Canvas(target);
ByteBuffer tileBuffer = mBuffer.slice();
int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
@@ -323,7 +221,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
tile.copyPixelsFromBuffer(tileBuffer.asIntBuffer());
// Copy the tile to the master Bitmap and recycle it
- canvas.drawBitmap(tile, x, y, null);
+ c.drawBitmap(tile, x, y, null);
tile.recycle();
// Progress the buffer to the next tile
@@ -333,7 +231,16 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
}
}
+ @Override
+ protected void tileLayerUpdated() {
+ /* No-op. */
+ }
+
+ @Override
public Bitmap getBitmap() {
+ if (mTileLayer == null)
+ return null;
+
// Begin a tile transaction, otherwise the buffer can be destroyed while
// we're reading from it.
beginTransaction(mTileLayer);
@@ -341,21 +248,17 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
if (mBuffer == null || mBufferSize.width <= 0 || mBufferSize.height <= 0)
return null;
try {
- Bitmap bitmap = null;
+ Bitmap b = null;
if (mTileLayer instanceof MultiTileLayer) {
- bitmap = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
+ b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat));
- copyPixelsFromMultiTileLayer(bitmap);
- } else if (mTileLayer instanceof SingleTileLayer) {
- bitmap = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
- CairoUtils.cairoFormatTobitmapConfig(mFormat));
- bitmap.copyPixelsFromBuffer(mBuffer.asIntBuffer());
+ copyPixelsFromMultiTileLayer(b);
} else {
Log.w(LOGTAG, "getBitmap() called on a layer (" + mTileLayer + ") we don't know how to get a bitmap from");
}
- return bitmap;
+ return b;
} catch (OutOfMemoryError oom) {
Log.w(LOGTAG, "Unable to create bitmap", oom);
return null;
@@ -365,9 +268,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
}
}
- /**
- * Returns the back buffer. This function is for Gecko to use.
- */
+ /** Returns the back buffer. This function is for Gecko to use. */
public ByteBuffer lockBuffer() {
return mBuffer;
}
@@ -381,125 +282,41 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
}
@Override
- public void geometryChanged() {
- /* Let Gecko know if the screensize has changed */
- sendResizeEventIfNecessary();
- render();
- }
-
- private void sendResizeEventIfNecessary() {
- sendResizeEventIfNecessary(false);
- }
-
- /* Informs Gecko that the screen size has changed. */
- private void sendResizeEventIfNecessary(boolean force) {
- DisplayMetrics metrics = new DisplayMetrics();
- //GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- LibreOfficeMainActivity.mAppContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
-
- // Return immediately if the screen size hasn't changed or the viewport
- // size is zero (which indicates that the rendering surface hasn't been
- // allocated yet).
- boolean screenSizeChanged = (metrics.widthPixels != mScreenSize.width ||
- metrics.heightPixels != mScreenSize.height);
- boolean viewportSizeValid = (getLayerController() != null &&
- getLayerController().getViewportSize().isPositive());
- if (!(force || (screenSizeChanged && viewportSizeValid))) {
- return;
- }
-
- mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
- IntSize bufferSize;
-
- // Round up depending on layer implementation to remove texture wastage
- if (mTileLayer instanceof MultiTileLayer) {
- // Round to the next multiple of the tile size, respecting maximum texture size
- bufferSize = new IntSize(((mScreenSize.width + LayerController.MIN_BUFFER.width - 1) / TILE_SIZE.width + 1) * TILE_SIZE.width,
- ((mScreenSize.height + LayerController.MIN_BUFFER.height - 1) / TILE_SIZE.height + 1) * TILE_SIZE.height);
-
- } else {
- int maxSize = getLayerController().getView().getMaxTextureSize();
-
- // XXX Integrate gralloc/tiling work to circumvent this
- if (mScreenSize.width > maxSize || mScreenSize.height > maxSize)
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list