Bug 721070 - Checkerboarding at bottom after pinch zooming out. r=kats,pcwalton

Certain conditions would cause MultiTileLayer to incorrectly invalidate tiles,
or to reuse tiles incorrectly, which would cause checkerboarding (sometimes
permanent until a redraw occurs).

This addresses said issues:

- Removes manual invalidation on Document:Shown and Tab:Selected. This is
  unnecessary, as the entire buffer will be invalidated when this happens
  anyway. Sometimes Document:Shown happens *after* drawing has occurred,
  which caused the entire screen to checkerboard incorrectly.
- Fix re-using off-screen tiles with the incorrect resolution. Tiles are stored
  in a hash-map based on their unscaled position. As only tiles that intersect
  with the update region in tile-space are invalidated, sometimes tiles that
  were off-screen, but whose unscaled tile origin appears on-screen would be
  incorrectly re-used. Fix this by checking that a tile's resolution matches the
  current resolution before reusing it.
This commit is contained in:
Chris Lord 2012-01-26 20:19:35 +00:00
Родитель ccf4980df5
Коммит 773061c1f7
2 изменённых файлов: 32 добавлений и 15 удалений

Просмотреть файл

@ -162,8 +162,6 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateAndDraw", this);
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
GeckoAppShell.registerGeckoEventListener("Document:Shown", this);
GeckoAppShell.registerGeckoEventListener("Tab:Selected:Done", this);
sendResizeEventIfNecessary();
}
@ -252,7 +250,6 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
Point tileOrigin = new Point((origin.x / TILE_SIZE.width) * TILE_SIZE.width,
(origin.y / TILE_SIZE.height) * TILE_SIZE.height);
mRenderOffset.set(origin.x - tileOrigin.x, origin.y - tileOrigin.y);
((MultiTileLayer)mTileLayer).invalidateBuffer();
}
// If the window size has changed, reallocate the buffer to match.
@ -519,16 +516,6 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.DRAW, rect));
} else if ("Viewport:UpdateLater".equals(event)) {
mUpdateViewportOnEndDraw = true;
} else if (("Document:Shown".equals(event) ||
"Tab:Selected:Done".equals(event)) &&
(mTileLayer instanceof MultiTileLayer)) {
beginTransaction(mTileLayer);
try {
((MultiTileLayer)mTileLayer).invalidateTiles();
((MultiTileLayer)mTileLayer).invalidateBuffer();
} finally {
endTransaction(mTileLayer);
}
}
}

Просмотреть файл

@ -333,7 +333,7 @@ public class MultiTileLayer extends Layer {
}
// Dirty tile, find out if we already have this tile to reuse.
boolean reusedTile = true;
boolean reusedTile;
Point tileOrigin = new Point(x, y);
SubTile tile = mPositionHash.get(longFromPoint(tileOrigin));
@ -343,6 +343,10 @@ public class MultiTileLayer extends Layer {
reusedTile = false;
} else {
mTiles.remove(tile);
// Reuse the tile (i.e. keep the texture data and metrics)
// only if the resolution matches
reusedTile = FloatUtils.fuzzyEquals(tile.getResolution(), getResolution());
}
// Place tile at the end of the tile-list so it isn't re-used.
@ -396,10 +400,36 @@ public class MultiTileLayer extends Layer {
@Override
public void draw(RenderContext context) {
for (SubTile layer : mTiles) {
// Skip invalid tiles
if (layer.key == null) {
continue;
}
// Avoid work, only draw tiles that intersect with the viewport
RectF layerBounds = layer.getBounds(context, new FloatSize(layer.getSize()));
if (RectF.intersects(layerBounds, context.viewport))
if (RectF.intersects(layerBounds, context.viewport)) {
layer.draw(context);
}
}
}
@Override
public void setOrigin(Point origin) {
Point oldOrigin = getOrigin();
if (!origin.equals(oldOrigin)) {
super.setOrigin(origin);
invalidateBuffer();
}
}
@Override
public void setResolution(float resolution) {
float oldResolution = getResolution();
if (!FloatUtils.fuzzyEquals(resolution, oldResolution)) {
super.setResolution(resolution);
invalidateBuffer();
}
}