Bug 703141 - Restore usage of the redraw hint. r=kats

Earlier patches mistakenly removed the redraw hint. This restores it, and
alters its behaviour to work correctly with regards to the viewport. This
should help mitigate some checker-boarding and performance issues when panning
and zooming.
This commit is contained in:
Chris Lord 2011-11-23 19:08:20 +00:00
parent 3bc8eb0f77
commit 133e2a7438
4 changed files with 79 additions and 26 deletions

View File

@ -59,8 +59,6 @@ import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.TimerTask;
/**
* Transfers a software-rendered Gecko to an ImageLayer so that it can be rendered by our
@ -79,6 +77,8 @@ public class GeckoSoftwareLayerClient extends LayerClient {
/* The viewport rect that Gecko is currently displaying. */
private ViewportMetrics mGeckoViewport;
private boolean mPendingViewportReply;
private boolean mPendingViewportSet;
/* Gecko has loaded new content, let its viewport metrics completely
* override the LayerController on the next draw.
@ -89,7 +89,7 @@ public class GeckoSoftwareLayerClient extends LayerClient {
private static final long MIN_VIEWPORT_CHANGE_DELAY = 350L;
private long mLastViewportChangeTime;
private Timer mViewportRedrawTimer;
private boolean mPendingViewportAdjust;
public GeckoSoftwareLayerClient(Context context) {
mContext = context;
@ -162,6 +162,13 @@ public class GeckoSoftwareLayerClient extends LayerClient {
if (FloatUtils.fuzzyEquals(controller.getZoomFactor(), mGeckoViewport.getZoomFactor()))
controller.setPageSize(mGeckoViewport.getPageSize());
}
Log.i(LOGTAG, "Viewport adjusted");
mPendingViewportReply = false;
if (mPendingViewportSet) {
mPendingViewportSet = false;
adjustViewportWithThrottling();
}
}
});
}
@ -228,24 +235,20 @@ public class GeckoSoftwareLayerClient extends LayerClient {
if (!getLayerController().getRedrawHint())
return;
if (System.currentTimeMillis() < mLastViewportChangeTime + MIN_VIEWPORT_CHANGE_DELAY) {
if (mViewportRedrawTimer != null)
return;
if (mPendingViewportSet || mPendingViewportAdjust)
return;
mViewportRedrawTimer = new Timer();
mViewportRedrawTimer.schedule(new TimerTask() {
@Override
public void run() {
/* We jump back to the UI thread to avoid possible races here. */
getLayerController().getView().post(new Runnable() {
@Override
public void run() {
mViewportRedrawTimer = null;
adjustViewportWithThrottling();
}
});
}
}, MIN_VIEWPORT_CHANGE_DELAY);
long timeDelta = System.currentTimeMillis() - mLastViewportChangeTime;
if (timeDelta < MIN_VIEWPORT_CHANGE_DELAY) {
getLayerController().getView().postDelayed(
new Runnable() {
@Override
public void run() {
mPendingViewportAdjust = false;
adjustViewportWithThrottling();
}
}, MIN_VIEWPORT_CHANGE_DELAY - timeDelta);
mPendingViewportAdjust = true;
return;
}
@ -253,6 +256,13 @@ public class GeckoSoftwareLayerClient extends LayerClient {
}
private void adjustViewport() {
if (mPendingViewportReply) {
mPendingViewportSet = true;
return;
}
Log.i(LOGTAG, "Adjusting viewport");
mPendingViewportReply = true;
ViewportMetrics viewportMetrics =
new ViewportMetrics(getLayerController().getViewportMetrics());

View File

@ -80,18 +80,21 @@ public class LayerController {
private OnTouchListener mOnTouchListener; /* The touch listener. */
private LayerClient mLayerClient; /* The layer client. */
private boolean mForceRedraw;
/* NB: These must be powers of two due to the OpenGL ES 1.x restriction on NPOT textures. */
public static final int TILE_WIDTH = 1024;
public static final int TILE_HEIGHT = 2048;
/* 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 = 150;
private static final int DANGER_ZONE_Y = 300;
private static final int DANGER_ZONE_X = 75;
private static final int DANGER_ZONE_Y = 150;
public LayerController(Context context) {
mContext = context;
mForceRedraw = true;
mViewportMetrics = new ViewportMetrics();
mPanZoomController = new PanZoomController(this);
mView = new LayerView(context, this);
@ -104,6 +107,10 @@ public class LayerController {
layerClient.setLayerController(this);
}
public void setForceRedraw() {
mForceRedraw = true;
}
public LayerClient getLayerClient() { return mLayerClient; }
public Layer getRoot() { return mRootLayer; }
public LayerView getView() { return mView; }
@ -153,6 +160,7 @@ public class LayerController {
*/
public void setViewportSize(FloatSize size) {
mViewportMetrics.setSize(size);
setForceRedraw();
notifyLayerClientOfGeometryChange();
mPanZoomController.geometryChanged();
@ -231,7 +239,12 @@ public class LayerController {
* would prefer that the action didn't take place.
*/
public boolean getRedrawHint() {
return true;//aboutToCheckerboard();
if (mForceRedraw) {
mForceRedraw = false;
return true;
}
return aboutToCheckerboard() && mPanZoomController.getRedrawHint();
}
private RectF getTileRect() {
@ -241,9 +254,17 @@ public class LayerController {
// Returns true if a checkerboard is about to be visible.
private boolean aboutToCheckerboard() {
RectF adjustedTileRect =
RectUtils.contract(getTileRect(), DANGER_ZONE_X, DANGER_ZONE_Y);
return !adjustedTileRect.contains(new RectF(mViewportMetrics.getViewport()));
// 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 = getPageSize();
RectF adjustedViewport = RectUtils.expand(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 !getTileRect().contains(adjustedViewport);
}
/**

View File

@ -73,6 +73,15 @@ public final class RectUtils {
rect.bottom - halfLessHeight);
}
public static RectF expand(RectF rect, float moreWidth, float moreHeight) {
float halfMoreWidth = moreWidth / 2;
float halfMoreHeight = moreHeight / 2;
return new RectF(rect.left - halfMoreWidth,
rect.top - halfMoreHeight,
rect.right + halfMoreWidth,
rect.bottom + halfMoreHeight);
}
public static RectF intersect(RectF one, RectF two) {
float left = Math.max(one.left, two.left);
float top = Math.max(one.top, two.top);

View File

@ -368,10 +368,15 @@ public class PanZoomController
private void stop() {
mState = PanZoomState.NOTHING;
if (mFlingTimer != null) {
mFlingTimer.cancel();
mFlingTimer = null;
}
// Force a viewport synchronisation
mController.setForceRedraw();
mController.notifyLayerClientOfGeometryChange();
}
}
@ -626,6 +631,10 @@ public class PanZoomController
mY.firstTouchPos = mY.touchPos = detector.getFocusY();
GeckoApp.mAppContext.showPluginViews();
// Force a viewport synchronisation
mController.setForceRedraw();
mController.notifyLayerClientOfGeometryChange();
}
@Override
@ -646,4 +655,8 @@ public class PanZoomController
GeckoEvent e = new GeckoEvent("Gesture:LongPress", ret.toString());
GeckoAppShell.sendEventToGecko(e);
}
public boolean getRedrawHint() {
return (mState != PanZoomState.PINCHING);
}
}