summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-09-23 19:12:41 +0200
committerTomaž Vajngerl <tomaz.vajngerl@collabora.com>2014-09-24 20:43:02 +0200
commitcc2f2afd7e2fd3d34ccdcba2a3d25887bd9d5197 (patch)
tree219eedc36ba4982de2aba4443a6e1172336252e3 /android
parentb85c779595d679a3d24de37751b27fe70e878149 (diff)
android: add DisplayPortCalculator and DisplayPortMetrics
Change-Id: I1418023011cf0ef3611e3fda6f313d9fcb9ccea7
Diffstat (limited to 'android')
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java101
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java51
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java70
-rw-r--r--android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java2
4 files changed, 157 insertions, 67 deletions
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java
new file mode 100644
index 000000000000..4895858ea198
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java
@@ -0,0 +1,101 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.gfx;
+
+import android.graphics.RectF;
+import org.mozilla.gecko.util.FloatUtils;
+
+final class DisplayPortCalculator {
+ private static final String LOGTAG = "GeckoDisplayPortCalculator";
+
+ private static final int DEFAULT_DISPLAY_PORT_MARGIN = 300;
+
+ /* If the visible rect is within the danger zone (measured in pixels from each edge of a tile),
+ * we start aggressively redrawing to minimize checkerboarding. */
+ private static final int DANGER_ZONE_X = 75;
+ private static final int DANGER_ZONE_Y = 150;
+
+ static DisplayPortMetrics calculate(ImmutableViewportMetrics metrics) {
+ float desiredXMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
+ float desiredYMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
+
+ // we need to avoid having a display port that is larger than the page, or we will end up
+ // painting things outside the page bounds (bug 729169). we simultaneously need to make
+ // the display port as large as possible so that we redraw less.
+
+ // figure out how much of the desired buffer amount we can actually use on the horizontal axis
+ float xBufferAmount = Math.min(desiredXMargins, metrics.pageSizeWidth - metrics.getWidth());
+ // if we reduced the buffer amount on the horizontal axis, we should take that saved memory and
+ // use it on the vertical axis
+ float savedPixels = (desiredXMargins - xBufferAmount) * (metrics.getHeight() + desiredYMargins);
+ float extraYAmount = (float)Math.floor(savedPixels / (metrics.getWidth() + xBufferAmount));
+ float yBufferAmount = Math.min(desiredYMargins + extraYAmount, metrics.pageSizeHeight - metrics.getHeight());
+ // and the reverse - if we shrunk the buffer on the vertical axis we can add it to the horizontal
+ if (xBufferAmount == desiredXMargins && yBufferAmount < desiredYMargins) {
+ savedPixels = (desiredYMargins - yBufferAmount) * (metrics.getWidth() + xBufferAmount);
+ float extraXAmount = (float)Math.floor(savedPixels / (metrics.getHeight() + yBufferAmount));
+ xBufferAmount = Math.min(xBufferAmount + extraXAmount, metrics.pageSizeWidth - metrics.getWidth());
+ }
+
+ // and now calculate the display port margins based on how much buffer we've decided to use and
+ // the page bounds, ensuring we use all of the available buffer amounts on one side or the other
+ // on any given axis. (i.e. if we're scrolled to the top of the page, the vertical buffer is
+ // entirely below the visible viewport, but if we're halfway down the page, the vertical buffer
+ // is split).
+ float leftMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.viewportRectLeft);
+ float rightMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.pageSizeWidth - (metrics.viewportRectLeft + metrics.getWidth()));
+ if (leftMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
+ rightMargin = xBufferAmount - leftMargin;
+ } else if (rightMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
+ leftMargin = xBufferAmount - rightMargin;
+ } else if (!FloatUtils.fuzzyEquals(leftMargin + rightMargin, xBufferAmount)) {
+ float delta = xBufferAmount - leftMargin - rightMargin;
+ leftMargin += delta / 2;
+ rightMargin += delta / 2;
+ }
+
+ float topMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.viewportRectTop);
+ float bottomMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.pageSizeHeight - (metrics.viewportRectTop + metrics.getHeight()));
+ if (topMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
+ bottomMargin = yBufferAmount - topMargin;
+ } else if (bottomMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
+ topMargin = yBufferAmount - bottomMargin;
+ } else if (!FloatUtils.fuzzyEquals(topMargin + bottomMargin, yBufferAmount)) {
+ float delta = yBufferAmount - topMargin - bottomMargin;
+ topMargin += delta / 2;
+ bottomMargin += delta / 2;
+ }
+
+ // note that unless the viewport size changes, or the page dimensions change (either because of
+ // content changes or zooming), the size of the display port should remain constant. this
+ // is intentional to avoid re-creating textures and all sorts of other reallocations in the
+ // draw and composition code.
+ return new DisplayPortMetrics(metrics.viewportRectLeft - leftMargin,
+ metrics.viewportRectTop - topMargin,
+ metrics.viewportRectRight + rightMargin,
+ metrics.viewportRectBottom + bottomMargin,
+ metrics.zoomFactor);
+ }
+
+ // Returns true if a checkerboard is about to be visible.
+ static boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, DisplayPortMetrics displayPort) {
+ if (displayPort == null) {
+ return true;
+ }
+
+ // Increase the size of the viewport (and clamp to page boundaries), and
+ // intersect it with the tile's displayport to determine whether we're
+ // close to checkerboarding.
+ FloatSize pageSize = metrics.getPageSize();
+ RectF adjustedViewport = RectUtils.expand(metrics.getViewport(), DANGER_ZONE_X, DANGER_ZONE_Y);
+ if (adjustedViewport.top < 0) adjustedViewport.top = 0;
+ if (adjustedViewport.left < 0) adjustedViewport.left = 0;
+ if (adjustedViewport.right > pageSize.width) adjustedViewport.right = pageSize.width;
+ if (adjustedViewport.bottom > pageSize.height) adjustedViewport.bottom = pageSize.height;
+
+ return !displayPort.contains(adjustedViewport);
+ }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java
new file mode 100644
index 000000000000..c657deacfc4b
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/DisplayPortMetrics.java
@@ -0,0 +1,51 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.gfx;
+
+import android.graphics.RectF;
+
+/*
+ * This class keeps track of the area we request Gecko to paint, as well
+ * as the resolution of the paint. The area may be different from the visible
+ * area of the page, and the resolution may be different from the resolution
+ * used in the compositor to render the page. This is so that we can ask Gecko
+ * to paint a much larger area without using extra memory, and then render some
+ * subsection of that with compositor scaling.
+ */
+public final class DisplayPortMetrics {
+ private final RectF mPosition;
+ private final float mResolution;
+
+ public DisplayPortMetrics() {
+ this(0, 0, 0, 0, 1);
+ }
+
+ public DisplayPortMetrics(float left, float top, float right, float bottom, float resolution) {
+ mPosition = new RectF(left, top, right, bottom);
+ mResolution = resolution;
+ }
+
+ public boolean contains(RectF rect) {
+ return mPosition.contains(rect);
+ }
+
+ public String toJSON() {
+ StringBuffer sb = new StringBuffer(256);
+ sb.append("{ \"left\": ").append(mPosition.left)
+ .append(", \"top\": ").append(mPosition.top)
+ .append(", \"right\": ").append(mPosition.right)
+ .append(", \"bottom\": ").append(mPosition.bottom)
+ .append(", \"resolution\": ").append(mResolution)
+ .append('}');
+ return sb.toString();
+ }
+
+ public String toString() {
+ return "DisplayPortMetrics(" + mPosition.left + ","
+ + mPosition.top + "," + mPosition.right + ","
+ + mPosition.bottom + "," + mResolution + ")";
+ }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index e7a9059a953b..06613a4739de 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -54,13 +54,12 @@ import java.util.List;
public class GeckoLayerClient {
private static final String LOGTAG = "GeckoLayerClient";
- private static final int DEFAULT_DISPLAY_PORT_MARGIN = 300;
private static final long MIN_VIEWPORT_CHANGE_DELAY = 25L;
private static final IntSize TILE_SIZE = new IntSize(256, 256);
protected IntSize mScreenSize;
- private RectF mDisplayPort;
+ private DisplayPortMetrics mDisplayPort;
protected Layer mTileLayer;
/* The viewport that Gecko is currently displaying. */
protected ViewportMetrics mGeckoViewport;
@@ -82,7 +81,7 @@ public class GeckoLayerClient {
public GeckoLayerClient(Context context) {
mContext = context;
mScreenSize = new IntSize(0, 0);
- mDisplayPort = new RectF();
+ mDisplayPort = new DisplayPortMetrics();
}
protected void setupLayer() {
@@ -136,7 +135,7 @@ public class GeckoLayerClient {
Log.i(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - endDrawing");
}
- RectF getDisplayPort() {
+ DisplayPortMetrics getDisplayPort() {
return mDisplayPort;
}
@@ -221,74 +220,13 @@ public class GeckoLayerClient {
mViewportSizeChanged = true;
}
- private static RectF calculateDisplayPort(ImmutableViewportMetrics metrics) {
- float desiredXMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
- float desiredYMargins = 2 * DEFAULT_DISPLAY_PORT_MARGIN;
-
- // we need to avoid having a display port that is larger than the page, or we will end up
- // painting things outside the page bounds (bug 729169). we simultaneously need to make
- // the display port as large as possible so that we redraw less.
-
- // figure out how much of the desired buffer amount we can actually use on the horizontal axis
- float xBufferAmount = Math.min(desiredXMargins, metrics.pageSizeWidth - metrics.getWidth());
- // if we reduced the buffer amount on the horizontal axis, we should take that saved memory and
- // use it on the vertical axis
- float savedPixels = (desiredXMargins - xBufferAmount) * (metrics.getHeight() + desiredYMargins);
- float extraYAmount = (float)Math.floor(savedPixels / (metrics.getWidth() + xBufferAmount));
- float yBufferAmount = Math.min(desiredYMargins + extraYAmount, metrics.pageSizeHeight - metrics.getHeight());
- // and the reverse - if we shrunk the buffer on the vertical axis we can add it to the horizontal
- if (xBufferAmount == desiredXMargins && yBufferAmount < desiredYMargins) {
- savedPixels = (desiredYMargins - yBufferAmount) * (metrics.getWidth() + xBufferAmount);
- float extraXAmount = (float)Math.floor(savedPixels / (metrics.getHeight() + yBufferAmount));
- xBufferAmount = Math.min(xBufferAmount + extraXAmount, metrics.pageSizeWidth - metrics.getWidth());
- }
-
- // and now calculate the display port margins based on how much buffer we've decided to use and
- // the page bounds, ensuring we use all of the available buffer amounts on one side or the other
- // on any given axis. (i.e. if we're scrolled to the top of the page, the vertical buffer is
- // entirely below the visible viewport, but if we're halfway down the page, the vertical buffer
- // is split).
- float leftMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.viewportRectLeft);
- float rightMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.pageSizeWidth - (metrics.viewportRectLeft + metrics.getWidth()));
- if (leftMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
- rightMargin = xBufferAmount - leftMargin;
- } else if (rightMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
- leftMargin = xBufferAmount - rightMargin;
- } else if (!FloatUtils.fuzzyEquals(leftMargin + rightMargin, xBufferAmount)) {
- float delta = xBufferAmount - leftMargin - rightMargin;
- leftMargin += delta / 2;
- rightMargin += delta / 2;
- }
-
- float topMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.viewportRectTop);
- float bottomMargin = Math.min(DEFAULT_DISPLAY_PORT_MARGIN, metrics.pageSizeHeight - (metrics.viewportRectTop + metrics.getHeight()));
- if (topMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
- bottomMargin = yBufferAmount - topMargin;
- } else if (bottomMargin < DEFAULT_DISPLAY_PORT_MARGIN) {
- topMargin = yBufferAmount - bottomMargin;
- } else if (!FloatUtils.fuzzyEquals(topMargin + bottomMargin, yBufferAmount)) {
- float delta = yBufferAmount - topMargin - bottomMargin;
- topMargin += delta / 2;
- bottomMargin += delta / 2;
- }
-
- // note that unless the viewport size changes, or the page dimensions change (either because of
- // content changes or zooming), the size of the display port should remain constant. this
- // is intentional to avoid re-creating textures and all sorts of other reallocations in the
- // draw and composition code.
- return new RectF(metrics.viewportRectLeft - leftMargin,
- metrics.viewportRectTop - topMargin,
- metrics.viewportRectRight + rightMargin,
- metrics.viewportRectBottom + bottomMargin);
- }
-
private void adjustViewport() {
ViewportMetrics viewportMetrics =
new ViewportMetrics(mLayerController.getViewportMetrics());
viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
- mDisplayPort = calculateDisplayPort(mLayerController.getViewportMetrics());
+ mDisplayPort = DisplayPortCalculator.calculate(mLayerController.getViewportMetrics());
LOKitShell.sendEvent(LOEvent.viewport(viewportMetrics));
if (mViewportSizeChanged) {
diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
index b9d80d9de7e3..461b53cde760 100644
--- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
+++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java
@@ -358,7 +358,7 @@ public class LayerController {
if (adjustedViewport.right > pageSize.width) adjustedViewport.right = pageSize.width;
if (adjustedViewport.bottom > pageSize.height) adjustedViewport.bottom = pageSize.height;
- RectF displayPort = (mLayerClient == null ? new RectF() : mLayerClient.getDisplayPort());
+ DisplayPortMetrics displayPort = (mLayerClient == null ? new DisplayPortMetrics() : mLayerClient.getDisplayPort());
return !displayPort.contains(adjustedViewport);
}