- handle limiting of unused loaded tiles in limitCache

- remove unused tiles based on distance to map center
This commit is contained in:
Hannes Janetzek 2013-02-04 17:56:47 +01:00
parent 10381ae4ea
commit 7df1ceeff1
2 changed files with 43 additions and 86 deletions

View File

@ -255,6 +255,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
private static void uploadTileData(MapTile tile) {
TileManager.tilesForUpload--;
if (tile.layers == null) {
BufferObject.release(tile.vbo);
tile.vbo = null;

View File

@ -18,7 +18,6 @@ package org.oscim.renderer;
import static org.oscim.generator.JobTile.STATE_LOADING;
import static org.oscim.generator.JobTile.STATE_NEW_DATA;
import static org.oscim.generator.JobTile.STATE_NONE;
import static org.oscim.generator.JobTile.STATE_READY;
import java.util.ArrayList;
import java.util.Arrays;
@ -37,13 +36,17 @@ import android.util.Log;
/**
* @author Hannes Janetzek
* @TODO
* - prefetching to cache file
* - this class should probably not be in 'renderer' -> tilemap?
* - make it general for reuse in tile-overlays
*/
public class TileManager {
static final String TAG = TileManager.class.getSimpleName();
private static final int MAX_TILES_IN_QUEUE = 40;
// TODO this should depend on the number of
// tiles that could be displayed
private static final int MAX_TILES_IN_QUEUE = 50;
private static final int CACHE_THRESHOLD = 30;
private final MapView mMapView;
@ -63,9 +66,6 @@ public class TileManager {
// new jobs for MapWorkers
private ArrayList<JobTile> mJobs;
// tiles that have new data to upload, see passTile()
private ArrayList<MapTile> mTilesLoaded;
private boolean mInitialized;
// private static MapPosition mCurPosition, mDrawPosition;
@ -75,6 +75,8 @@ public class TileManager {
private static int mUpdateCnt;
static Object tilelock = new Object();
static volatile int tilesForUpload;
private static TileSet mCurrentTiles;
/* package */static TileSet mNewTiles;
@ -138,10 +140,11 @@ public class TileManager {
mJobs = new ArrayList<JobTile>();
mTiles = new MapTile[GLRenderer.CACHE_TILES];
mTilesLoaded = new ArrayList<MapTile>(30);
mTilesSize = 0;
mUpdateCnt = 0;
tilesForUpload = 0;
mInitialized = false;
}
@ -182,8 +185,6 @@ public class TileManager {
mTilesSize = 0;
mTilesCount = 0;
mTilesLoaded.clear();
for (TileSet td : mTileSets) {
Arrays.fill(td.tiles, null);
td.cnt = 0;
@ -233,10 +234,9 @@ public class TileManager {
mMapView.render();
int remove = mTilesCount - GLRenderer.CACHE_TILES;
if (remove > CACHE_THRESHOLD)
if (remove > CACHE_THRESHOLD ||
tilesForUpload > (MAX_TILES_IN_QUEUE + 10))
limitCache(mapPosition, remove);
limitLoadQueue();
}
}
@ -282,9 +282,12 @@ public class TileManager {
return td;
}
// public void releaseTiles(TileSet tiles) {
//
// }
/**
* @param tiles ...
*/
public void releaseTiles(TileSet tiles) {
}
/**
* set mNewTiles for the visible tiles and pass it to GLRenderer, add jobs
@ -403,12 +406,10 @@ public class TileManager {
if (p == null) {
p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
QuadTree.add(p);
p.state = STATE_LOADING;
mJobs.add(p);
} else if (!p.isActive()) {
//Log.d(TAG, "prefetch parent " + p);
p.state = STATE_LOADING;
mJobs.add(p);
}
@ -505,18 +506,11 @@ public class TileManager {
remove--;
}
if (remove > 10) {
if (remove > 10 || tilesForUpload > MAX_TILES_IN_QUEUE) {
updateTileDistances(tiles, size, mapPosition);
// double start, end;
// start = SystemClock.uptimeMillis();
TileDistanceSort.sort(tiles, 0, size);
//end = SystemClock.uptimeMillis();
//Log.d(TAG, "sort took " + (end - start) +
// "limitCache: repacked: " + mTilesSize + " to: " + mTilesCount);
// sorting also repacks the 'sparse' filled array
// so end of mTiles is at mTilesCount now
mTilesSize = size = mTilesCount;
@ -528,66 +522,33 @@ public class TileManager {
Log.d(TAG, "limitCache: tile still locked " + t + " " + t.distance);
//mTiles.add(t);
} else if (t.state == STATE_LOADING) {
// NOTE: if we add tile back and set loading=false, on next
// limitCache the tile will be removed. clearTile could
// interfere with TileGenerator. so clear in passTile()
// instead.
// ... no, this does not work either: when set loading to
// false tile could be added to load queue while still
// processed in TileGenerator => need tile.cancel flag.
// NOTE: when set loading to false the tile could be
// added to load queue again while still processed in
// TileGenerator => need tile.cancel flag.
// t.isLoading = false;
//mTiles.add(t);
Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance);
} else {
if (t.state == STATE_NEW_DATA)
tilesForUpload--;
clearTile(t);
tiles[size - i] = null;
}
}
}
}
private void limitLoadQueue() {
int size = mTilesLoaded.size();
remove = (tilesForUpload - MAX_TILES_IN_QUEUE);
//Log.d(TAG, "cleanup load queue " + tilesForUpload + "/" + remove);
if (size < MAX_TILES_IN_QUEUE)
return;
synchronized (mTilesLoaded) {
// remove tiles already uploaded to vbo
for (int i = 0; i < size;) {
MapTile t = mTilesLoaded.get(i);
if (t.state == STATE_READY || t.state == STATE_NONE) {
mTilesLoaded.remove(i);
size--;
continue;
for (int i = 1; i < size && remove > 0; i++) {
MapTile t = tiles[size - i];
if (t != null && t.state == STATE_NEW_DATA && !t.isLocked()) {
//Log.d(TAG, "remove from load queue " + t);
clearTile(t);
tiles[size - i] = null;
remove--;
tilesForUpload--;
}
i++;
}
if (size < MAX_TILES_IN_QUEUE)
return;
// clear loaded but not used tiles
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
MapTile t = mTilesLoaded.get(i);
if (t.isLocked()) {
i++;
continue;
}
mTilesLoaded.remove(i);
// remove reference from mTiles
MapTile[] tiles = mTiles;
for (int j = 0, m = mTilesSize; j < m; j++) {
if (t == tiles[j]) {
mTiles[j] = null;
break;
}
}
clearTile(t);
}
}
}
@ -595,8 +556,8 @@ public class TileManager {
/**
* called from MapWorker Thread when tile is loaded by TileGenerator
* @param jobTile
* ...
* @return ...
* Tile ready for upload to GL
* @return ... caller does not care
*/
public synchronized boolean passTile(JobTile jobTile) {
MapTile tile = (MapTile) jobTile;
@ -617,13 +578,12 @@ public class TileManager {
tile.state = STATE_NEW_DATA;
//if (tile.isVisible)
mMapView.render();
// locked means the tile is visible or referenced by
// a tile that might be visible.
if (tile.isLocked())
mMapView.render();
synchronized (mTilesLoaded) {
//if (!mTilesLoaded.contains(tile))
mTilesLoaded.add(tile);
}
tilesForUpload++;
return true;
}
@ -633,10 +593,5 @@ public class TileManager {
mWidth = w;
mHeight = h;
// size changed does not mean gl surface was recreated
// FIXME iirc this was the case before honeycomb
//if (mWidth > 0 && mHeight > 0)
// mInitialized = true;
}
}