android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java | 405 ---------- 1 file changed, 405 deletions(-)
New commits: commit c4057724c9359bb61c72c6414c0842f48b88e846 Author: Michael Weghorn <[email protected]> AuthorDate: Tue Nov 11 14:45:23 2025 +0100 Commit: Michael Weghorn <[email protected]> CommitDate: Wed Nov 12 01:43:32 2025 +0100 android: Drop unused DisplayPortStrategy subclasses Since Change-Id: I8e7154837ac928f6940cf8a96c507e9aab59fe7e Author: Michael Weghorn <[email protected]> Date: Tue Nov 11 14:38:20 2025 +0100 android: Drop unused DisplayPortCalculator.setStrategy , it's more obvious that they're unused. Change-Id: I544c5909348badc1c4895716eb3f6cbdec37c385 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193810 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java b/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java index ca55d5a6b507..934e4cb138c9 100644 --- a/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java +++ b/android/source/src/java/org/mozilla/gecko/gfx/DisplayPortCalculator.java @@ -174,97 +174,6 @@ final class DisplayPortCalculator { return rect; } - /** - * This class implements the variation where we basically don't bother with a display port. - */ - private static class NoMarginStrategy extends DisplayPortStrategy { - NoMarginStrategy(Map<String, Integer> prefs) { - // no prefs in this strategy - } - - public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { - return new DisplayPortMetrics(metrics.viewportRectLeft, - metrics.viewportRectTop, - metrics.viewportRectRight, - metrics.viewportRectBottom, - metrics.zoomFactor); - } - - public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) { - return true; - } - - @Override - public String toString() { - return "NoMarginStrategy"; - } - } - - /** - * This class implements the variation where we use a fixed-size margin on the display port. - * The margin is always 300 pixels in all directions, except when we are (a) approaching a page - * boundary, and/or (b) if we are limited by the page size. In these cases we try to maintain - * the area of the display port by (a) shifting the buffer to the other side on the same axis, - * and/or (b) increasing the buffer on the other axis to compensate for the reduced buffer on - * one axis. - */ - private static class FixedMarginStrategy extends DisplayPortStrategy { - // The length of each axis of the display port will be the corresponding view length - // multiplied by this factor. - private final float SIZE_MULTIPLIER; - - // If the visible rect is within the danger zone (measured as a fraction of the view size - // from the edge of the displayport) we start redrawing to minimize checkerboarding. - private final float DANGER_ZONE_X_MULTIPLIER; - private final float DANGER_ZONE_Y_MULTIPLIER; - - FixedMarginStrategy(Map<String, Integer> prefs) { - SIZE_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_MULTIPLIER, 2000); - DANGER_ZONE_X_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_DANGER_X, 100); - DANGER_ZONE_Y_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_DANGER_Y, 200); - } - - public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { - float displayPortWidth = metrics.getWidth() * SIZE_MULTIPLIER; - float displayPortHeight = metrics.getHeight() * SIZE_MULTIPLIER; - - // 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. reshape the display - // port dimensions to accomplish this. - FloatSize usableSize = reshapeForPage(displayPortWidth, displayPortHeight, metrics); - float horizontalBuffer = usableSize.width - metrics.getWidth(); - float verticalBuffer = usableSize.height - metrics.getHeight(); - - // 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). - RectF margins = new RectF(); - margins.left = horizontalBuffer / 2.0f; - margins.right = horizontalBuffer - margins.left; - margins.top = verticalBuffer / 2.0f; - margins.bottom = verticalBuffer - margins.top; - margins = shiftMarginsForPageBounds(margins, metrics); - - return getTileAlignedDisplayPortMetrics(margins, metrics.zoomFactor, metrics); - } - - public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) { - // Increase the size of the viewport based on the danger zone multiplier (and clamp to page - // boundaries), and intersect it with the current displayport to determine whether we're - // close to checkerboarding. - RectF adjustedViewport = expandByDangerZone(metrics.getViewport(), DANGER_ZONE_X_MULTIPLIER, DANGER_ZONE_Y_MULTIPLIER, metrics); - return !displayPort.contains(adjustedViewport); - } - - @Override - public String toString() { - return "FixedMarginStrategy mult=" + SIZE_MULTIPLIER + ", dangerX=" + DANGER_ZONE_X_MULTIPLIER + ", dangerY=" + DANGER_ZONE_Y_MULTIPLIER; - } - } - /** * This class implements the variation with a small fixed-size margin with velocity bias. * In this variation, the default margins are pretty small relative to the view size, but @@ -391,318 +300,4 @@ final class DisplayPortCalculator { + ", dangerIncrX=" + DANGER_ZONE_INCR_Y_MULTIPLIER + ", dangerIncrY=" + DANGER_ZONE_INCR_Y_MULTIPLIER; } } - - /** - * This class implements the variation where we draw more of the page at low resolution while panning. - * In this variation, as we pan faster, we increase the page area we are drawing, but reduce the draw - * resolution to compensate. This results in the same device-pixel area drawn; the compositor then - * scales this up to the viewport zoom level. This results in a large area of the page drawn but it - * looks blurry. The assumption is that drawing extra that we never display is better than checkerboarding, - * where we draw less but never even show it on the screen. - */ - private static class DynamicResolutionStrategy extends DisplayPortStrategy { - - // The velocity above which we start zooming out the display port to keep up - // with the panning. - private final float VELOCITY_EXPANSION_THRESHOLD; - - - DynamicResolutionStrategy(LibreOfficeMainActivity context, Map<String, Integer> prefs) { - // ignore prefs for now - VELOCITY_EXPANSION_THRESHOLD = LOKitShell.getDpi(context) / 16f; - VELOCITY_FAST_THRESHOLD = VELOCITY_EXPANSION_THRESHOLD * 2.0f; - } - - // The length of each axis of the display port will be the corresponding view length - // multiplied by this factor. - private static final float SIZE_MULTIPLIER = 1.5f; - - // How much we increase the display port based on velocity. Assuming no friction and - // splitting (see below), this should be the number of frames (@60fps) between us - // calculating the display port and the draw of the *next* display port getting composited - // and displayed on the screen. This is because the timeline looks like this: - // Java: pan pan pan pan pan pan ! pan pan pan pan pan pan ! - // Gecko: \-> draw -> composite / \-> draw -> composite / - // The display port calculated on the first "pan" gets composited to the screen at the - // first exclamation mark, and remains on the screen until the second exclamation mark. - // In order to avoid checkerboarding, that display port must be able to contain all of - // the panning until the second exclamation mark, which encompasses two entire draw/composite - // cycles. - // If we take into account friction, our velocity multiplier should be reduced as the - // amount of pan will decrease each time. If we take into account display port splitting, - // it should be increased as the splitting means some of the display port will be used to - // draw in the opposite direction of the velocity. For now I'm assuming these two cancel - // each other out. - private static final float VELOCITY_MULTIPLIER = 60.0f; - - // The following constants adjust how biased the display port is in the direction of panning. - // When panning fast (above the FAST_THRESHOLD) we use the fast split factor to split the - // display port "buffer" area, otherwise we use the slow split factor. This is based on the - // assumption that if the user is panning fast, they are less likely to reverse directions - // and go backwards, so we should spend more of our display port buffer in the direction of - // panning. - private final float VELOCITY_FAST_THRESHOLD; - private static final float FAST_SPLIT_FACTOR = 0.95f; - private static final float SLOW_SPLIT_FACTOR = 0.8f; - - // The following constants are used for viewport prediction; we use them to estimate where - // the viewport will be soon and whether or not we should trigger a draw right now. "soon" - // in the previous sentence really refers to the amount of time it would take to draw and - // composite from the point at which we do the calculation, and that is not really a known - // quantity. The velocity multiplier is how much we multiply the velocity by; it has the - // same caveats as the VELOCITY_MULTIPLIER above except that it only needs to take into account - // one draw/composite cycle instead of two. The danger zone multiplier is a multiplier of the - // viewport size that we use as an extra "danger zone" around the viewport; if this danger - // zone falls outside the display port then we are approaching the point at which we will - // checkerboard, and hence should start drawing. Note that if DANGER_ZONE_MULTIPLIER is - // greater than (SIZE_MULTIPLIER - 1.0f), then at zero velocity we will always be in the - // danger zone, and thus will be constantly drawing. - private static final float PREDICTION_VELOCITY_MULTIPLIER = 30.0f; - private static final float DANGER_ZONE_MULTIPLIER = 0.20f; // must be less than (SIZE_MULTIPLIER - 1.0f) - - public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { - float displayPortWidth = metrics.getWidth() * SIZE_MULTIPLIER; - float displayPortHeight = metrics.getHeight() * SIZE_MULTIPLIER; - - // for resolution calculation purposes, we need to know what the adjusted display port dimensions - // would be if we had zero velocity, so calculate that here before we increase the display port - // based on velocity. - FloatSize reshapedSize = reshapeForPage(displayPortWidth, displayPortHeight, metrics); - - // increase displayPortWidth and displayPortHeight based on the velocity, but maintaining their - // relative aspect ratio. - if (velocity.length() > VELOCITY_EXPANSION_THRESHOLD) { - float velocityFactor = Math.max(Math.abs(velocity.x) / displayPortWidth, - Math.abs(velocity.y) / displayPortHeight); - velocityFactor *= VELOCITY_MULTIPLIER; - - displayPortWidth += (displayPortWidth * velocityFactor); - displayPortHeight += (displayPortHeight * velocityFactor); - } - - // at this point, displayPortWidth and displayPortHeight are how much of the page (in device pixels) - // we want to be rendered by Gecko. Note here "device pixels" is equivalent to CSS pixels multiplied - // by metrics.zoomFactor - - // 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. reshape the display - // port dimensions to accomplish this. this may change the aspect ratio of the display port, - // but we are assuming that this is desirable because the advantages from pre-drawing will - // outweigh the disadvantages from any buffer reallocations that might occur. - FloatSize usableSize = reshapeForPage(displayPortWidth, displayPortHeight, metrics); - float horizontalBuffer = usableSize.width - metrics.getWidth(); - float verticalBuffer = usableSize.height - metrics.getHeight(); - - // at this point, horizontalBuffer and verticalBuffer are the dimensions of the buffer area we have. - // the buffer area is the off-screen area that is part of the display port and will be pre-drawn in case - // the user scrolls there. we now need to split the buffer area on each axis so that we know - // what the exact margins on each side will be. first we split the buffer amount based on the direction - // we're moving, so that we have a larger buffer in the direction of travel. - RectF margins = new RectF(); - margins.left = splitBufferByVelocity(horizontalBuffer, velocity.x); - margins.right = horizontalBuffer - margins.left; - margins.top = splitBufferByVelocity(verticalBuffer, velocity.y); - margins.bottom = verticalBuffer - margins.top; - - // then, we account for running into the page bounds - so that if we hit the top of the page, we need - // to drop the top margin and move that amount to the bottom margin. - margins = shiftMarginsForPageBounds(margins, metrics); - - // finally, we calculate the resolution we want to render the display port area at. We do this - // so that as we expand the display port area (because of velocity), we reduce the resolution of - // the painted area so as to maintain the size of the buffer Gecko is painting into. we calculate - // the reduction in resolution by comparing the display port size with and without the velocity - // changes applied. - // this effectively means that as we pan faster and faster, the display port grows, but we paint - // at lower resolutions. this paints more area to reduce checkerboard at the cost of increasing - // compositor-scaling and blurriness. Once we stop panning, the blurriness must be entirely gone. - // Note that usable* could be less than base* if we are pinch-zoomed out into overscroll, so we - // clamp it to make sure this doesn't increase our display resolution past metrics.zoomFactor. - float scaleFactor = Math.min(reshapedSize.width / usableSize.width, reshapedSize.height / usableSize.height); - float displayResolution = metrics.zoomFactor * Math.min(1.0f, scaleFactor); - - return new DisplayPortMetrics( - metrics.viewportRectLeft - margins.left, - metrics.viewportRectTop - margins.top, - metrics.viewportRectRight + margins.right, - metrics.viewportRectBottom + margins.bottom, - displayResolution); - } - - /** - * Split the given buffer amount into two based on the velocity. - * Given an amount of total usable buffer on an axis, this will - * return the amount that should be used on the left/top side of - * the axis (the side which a negative velocity vector corresponds - * to). - */ - private float splitBufferByVelocity(float amount, float velocity) { - // if no velocity, so split evenly - if (FloatUtils.fuzzyEquals(velocity, 0)) { - return amount / 2.0f; - } - // if we're moving quickly, assign more of the amount in that direction - // since is less likely that we will reverse direction immediately - if (velocity < -VELOCITY_FAST_THRESHOLD) { - return amount * FAST_SPLIT_FACTOR; - } - if (velocity > VELOCITY_FAST_THRESHOLD) { - return amount * (1.0f - FAST_SPLIT_FACTOR); - } - // if we're moving slowly, then assign less of the amount in that direction - if (velocity < 0) { - return amount * SLOW_SPLIT_FACTOR; - } else { - return amount * (1.0f - SLOW_SPLIT_FACTOR); - } - } - - public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) { - // Expand the viewport based on our velocity (and clamp it to page boundaries). - // Then intersect it with the last-requested displayport to determine whether we're - // close to checkerboarding. - - RectF predictedViewport = metrics.getViewport(); - - // first we expand the viewport in the direction we're moving based on some - // multiple of the current velocity. - if (velocity.length() > 0) { - if (velocity.x < 0) { - predictedViewport.left += velocity.x * PREDICTION_VELOCITY_MULTIPLIER; - } else if (velocity.x > 0) { - predictedViewport.right += velocity.x * PREDICTION_VELOCITY_MULTIPLIER; - } - - if (velocity.y < 0) { - predictedViewport.top += velocity.y * PREDICTION_VELOCITY_MULTIPLIER; - } else if (velocity.y > 0) { - predictedViewport.bottom += velocity.y * PREDICTION_VELOCITY_MULTIPLIER; - } - } - - // then we expand the viewport evenly in all directions just to have an extra - // safety zone. this also clamps it to page bounds. - predictedViewport = expandByDangerZone(predictedViewport, DANGER_ZONE_MULTIPLIER, DANGER_ZONE_MULTIPLIER, metrics); - return !displayPort.contains(predictedViewport); - } - - @Override - public String toString() { - return "DynamicResolutionStrategy"; - } - } - - /** - * This class implements the variation where we use the draw time to predict where we will be when - * a draw completes, and draw that instead of where we are now. In this variation, when our panning - * speed drops below a certain threshold, we draw 9 viewports' worth of content so that the user can - * pan in any direction without encountering checkerboarding. - * Once the user is panning, we modify the displayport to encompass an area range of where we think - * the user will be when the draw completes. This heuristic relies on both the estimated draw time - * the panning velocity; unexpected changes in either of these values will cause the heuristic to - * fail and show checkerboard. - */ - private static class PredictionBiasStrategy extends DisplayPortStrategy { - private static float VELOCITY_THRESHOLD; - - private int mPixelArea; // area of the viewport, used in draw time calculations - private int mMinFramesToDraw; // minimum number of frames we take to draw - private int mMaxFramesToDraw; // maximum number of frames we take to draw - - PredictionBiasStrategy(LibreOfficeMainActivity context, Map<String, Integer> prefs) { - VELOCITY_THRESHOLD = LOKitShell.getDpi(context) * getFloatPref(prefs, PREF_DISPLAYPORT_PB_VELOCITY_THRESHOLD, 16); - resetPageState(); - } - - public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { - float width = metrics.getWidth(); - float height = metrics.getHeight(); - mPixelArea = (int)(width * height); - - if (velocity.length() < VELOCITY_THRESHOLD) { - // if we're going slow, expand the displayport to 9x viewport size - RectF margins = new RectF(width, height, width, height); - return getTileAlignedDisplayPortMetrics(margins, metrics.zoomFactor, metrics); - } - - // figure out how far we expect to be - float minDx = velocity.x * mMinFramesToDraw; - float minDy = velocity.y * mMinFramesToDraw; - float maxDx = velocity.x * mMaxFramesToDraw; - float maxDy = velocity.y * mMaxFramesToDraw; - - // figure out how many pixels we will be drawing when we draw the above-calculated range. - // this will be larger than the viewport area. - float pixelsToDraw = (width + Math.abs(maxDx - minDx)) * (height + Math.abs(maxDy - minDy)); - // adjust how far we will get because of the time spent drawing all these extra pixels. this - // will again increase the number of pixels drawn so really we could keep iterating this over - // and over, but once seems enough for now. - maxDx = maxDx * pixelsToDraw / mPixelArea; - maxDy = maxDy * pixelsToDraw / mPixelArea; - - // and finally generate the displayport. the min/max stuff takes care of - // negative velocities as well as positive. - RectF margins = new RectF( - -Math.min(minDx, maxDx), - -Math.min(minDy, maxDy), - Math.max(minDx, maxDx), - Math.max(minDy, maxDy)); - return getTileAlignedDisplayPortMetrics(margins, metrics.zoomFactor, metrics); - } - - public boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) { - // the code below is the same as in calculate() but is awkward to refactor since it has multiple outputs. - // refer to the comments in calculate() to understand what this is doing. - float minDx = velocity.x * mMinFramesToDraw; - float minDy = velocity.y * mMinFramesToDraw; - float maxDx = velocity.x * mMaxFramesToDraw; - float maxDy = velocity.y * mMaxFramesToDraw; - float pixelsToDraw = (metrics.getWidth() + Math.abs(maxDx - minDx)) * (metrics.getHeight() + Math.abs(maxDy - minDy)); - maxDx = maxDx * pixelsToDraw / mPixelArea; - maxDy = maxDy * pixelsToDraw / mPixelArea; - - // now that we have an idea of how far we will be when the draw completes, take the farthest - // end of that range and see if it falls outside the displayport bounds. if it does, allow - // the draw to go through - RectF predictedViewport = metrics.getViewport(); - predictedViewport.left += maxDx; - predictedViewport.top += maxDy; - predictedViewport.right += maxDx; - predictedViewport.bottom += maxDy; - - predictedViewport = clampToPageBounds(predictedViewport, metrics); - return !displayPort.contains(predictedViewport); - } - - @Override - public boolean drawTimeUpdate(long millis, int pixels) { - // calculate the number of frames it took to draw a viewport-sized area - float normalizedTime = (float)mPixelArea * (float)millis / (float)pixels; - int normalizedFrames = (int)Math.ceil(normalizedTime * 60f / 1000f); - // broaden our range on how long it takes to draw if the draw falls outside - // the range. this allows it to grow gradually. this heuristic may need to - // be tweaked into more of a floating window average or something. - if (normalizedFrames <= mMinFramesToDraw) { - mMinFramesToDraw--; - } else if (normalizedFrames > mMaxFramesToDraw) { - mMaxFramesToDraw++; - } else { - return true; - } - Log.d(LOGTAG, "Widened draw range to [" + mMinFramesToDraw + ", " + mMaxFramesToDraw + "]"); - return true; - } - - @Override - public void resetPageState() { - mMinFramesToDraw = 0; - mMaxFramesToDraw = 2; - } - - @Override - public String toString() { - return "PredictionBiasStrategy threshold=" + VELOCITY_THRESHOLD; - } - } }
