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