From 7df1ceeff1a048886e843eaaf8f3285ff9839b40 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 4 Feb 2013 17:56:47 +0100 Subject: [PATCH] - handle limiting of unused loaded tiles in limitCache - remove unused tiles based on distance to map center --- src/org/oscim/renderer/GLRenderer.java | 2 + src/org/oscim/renderer/TileManager.java | 127 ++++++++---------------- 2 files changed, 43 insertions(+), 86 deletions(-) diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index 19133fd4..6deda80e 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -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; diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java index cc4dc263..ed3c1999 100644 --- a/src/org/oscim/renderer/TileManager.java +++ b/src/org/oscim/renderer/TileManager.java @@ -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 mJobs; - // tiles that have new data to upload, see passTile() - private ArrayList 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(); mTiles = new MapTile[GLRenderer.CACHE_TILES]; - mTilesLoaded = new ArrayList(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; } }