make TileManager non-static

This commit is contained in:
Hannes Janetzek 2013-02-06 11:08:17 +01:00
parent fada95f380
commit 7c6ec614a2
6 changed files with 175 additions and 186 deletions

View File

@ -255,29 +255,25 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
private static void uploadTileData(MapTile tile) {
TileManager.tilesForUpload--;
tile.state = STATE_READY;
if (tile.layers == null) {
BufferObject.release(tile.vbo);
tile.vbo = null;
} else {
int newSize = tile.layers.getSize();
if (tile.layers == null)
return;
if (newSize > 0) {
int newSize = tile.layers.getSize();
if (newSize > 0) {
if (tile.vbo == null)
tile.vbo = BufferObject.get(newSize);
if (tile.vbo == null)
tile.vbo = BufferObject.get(newSize);
if (!uploadLayers(tile.layers, tile.vbo, newSize, true)) {
Log.d(TAG, "uploadTileData " + tile + " failed!");
tile.layers.clear();
tile.layers = null;
BufferObject.release(tile.vbo);
tile.vbo = null;
}
if (!uploadLayers(tile.layers, tile.vbo, newSize, true)) {
Log.d(TAG, "BUG uploadTileData " + tile + " failed!");
tile.layers.clear();
tile.layers = null;
BufferObject.release(tile.vbo);
tile.vbo = null;
}
}
tile.state = STATE_READY;
}
private static void checkBufferUsage(boolean force) {
@ -352,7 +348,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
serial = mDrawTiles.serial;
// get current tiles to draw
mDrawTiles = TileManager.getActiveTiles(mDrawTiles);
mDrawTiles = mMapView.getTileManager().getActiveTiles(mDrawTiles);
// FIXME what if only drawing overlays?
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
@ -376,9 +372,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
MapTile[] tiles = mDrawTiles.tiles;
if (changed) {
// lock tiles while updating isVisible state
synchronized (GLRenderer.tilelock) {
// get visible tiles
for (int i = 0; i < tileCnt; i++)
tiles[i].isVisible = false;
@ -386,8 +382,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// zoom-level changed.
byte z = tiles[0].zoomLevel;
float div = FastMath.pow(z - pos.zoomLevel);
if (div != 1)
Log.d(TAG, "tiles not from current zoom level");
// transform screen coordinates to tile coordinates
float scale = pos.scale / div;
float px = (float) pos.x * div;
@ -398,7 +393,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
coords[i + 1] = (py + coords[i + 1] / scale) / Tile.TILE_SIZE;
}
// count placeholder tiles
mHolderCount = 0;
// check visibile tiles
mScanBox.scan(coords, z);
}
}
@ -520,9 +518,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
MapTile[] newTiles = mDrawTiles.tiles;
int cnt = mDrawTiles.cnt;
MapTile[] nextTiles;
synchronized (TileManager.tilelock) {
// ensure tiles keep visible state
synchronized (GLRenderer.tilelock) {
// lock tiles (and their proxies) to not be removed from cache
for (int i = 0; i < cnt; i++)
if (newTiles[i].isVisible)
@ -531,19 +530,15 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (td == null)
td = new TileSet(newTiles.length);
nextTiles = td.tiles;
// unlock previously active tiles
for (int i = 0, n = td.cnt; i < n; i++)
nextTiles[i].unlock();
}
td.tiles[i].unlock();
synchronized (GLRenderer.tilelock) {
// copy newTiles to nextTiles
td.cnt = 0;
for (int i = 0; i < cnt; i++)
if (newTiles[i].isVisible)
nextTiles[td.cnt++] = newTiles[i];
td.tiles[td.cnt++] = newTiles[i];
}
return td;
}

View File

@ -29,7 +29,6 @@ import org.oscim.generator.TileDistanceSort;
import org.oscim.renderer.layer.TextItem;
import org.oscim.renderer.layer.VertexPool;
import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
import android.util.Log;
@ -43,111 +42,64 @@ import android.util.Log;
public class TileManager {
static final String TAG = TileManager.class.getSimpleName();
// TODO this should depend on the number of
// tiles that could be displayed
private static final int MAX_TILES_IN_QUEUE = 50;
// limit number tiles with new data not uploaded to GL
// TODO this should depend on the number of tiles displayed
private static final int MAX_TILES_IN_QUEUE = 40;
// cache limit threshold
private static final int CACHE_THRESHOLD = 30;
private final MapView mMapView;
private final MapPosition mMapPosition;
private boolean mInitialized;
private int mWidth = 0;
private int mHeight = 0;
private final MapPosition mMapPosition = new MapPosition();
private final MapViewPosition mMapViewPosition;
// all tiles
// cache for all tiles
private MapTile[] mTiles;
// actual number of tiles in mTiles
private int mTilesCount;
// current end position in mTiles
private int mTilesSize;
// first free slot in mTiles
//private static int mTilesFirst;
// new jobs for MapWorkers
// counter for tiles with new data not uploaded to GL
private volatile int mTilesForUpload;
// new tile jobs for MapWorkers
private ArrayList<JobTile> mJobs;
private boolean mInitialized;
// counter to check whether current TileSet has changed
private static int mUpdateSerial;
// private static MapPosition mCurPosition, mDrawPosition;
private int mWidth = 0, mHeight = 0;
// lock for TileSets while updating MapTile locks
private Object mTilelock = new Object();
private TileSet mCurrentTiles;
/* package */TileSet mNewTiles;
private float[] mTileCoords = new float[8];
private static int mUpdateCnt;
static Object tilelock = new Object();
static volatile int tilesForUpload;
private static TileSet mCurrentTiles;
/* package */static TileSet mNewTiles;
private final ScanBox mScanBox = new ScanBox() {
@Override
public void setVisible(int y, int x1, int x2) {
MapTile[] tiles = mNewTiles.tiles;
int cnt = mNewTiles.cnt;
int max = tiles.length;
int xmax = 1 << mZoom;
for (int x = x1; x < x2; x++) {
MapTile tile = null;
if (cnt == max) {
Log.d(TAG, "reached maximum for currentTiles " + max);
break;
}
// NOTE to myself: do not modify x!
int xx = x;
if (x < 0 || x >= xmax) {
// flip-around date line
if (x < 0)
xx = xmax + x;
else
xx = x - xmax;
if (xx < 0 || xx >= xmax)
continue;
}
// check if tile is already added
for (int i = 0; i < cnt; i++)
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
tile = tiles[i];
break;
}
if (tile == null) {
tile = addTile(xx, y, mZoom, 0);
tiles[cnt++] = tile;
}
}
mNewTiles.cnt = cnt;
}
};
public void destroy() {
// there might be some leaks in here
// mRenderer = null;
// ... free pools
}
public TileManager(MapView mapView) {
Log.d(TAG, "init TileManager");
mMapView = mapView;
mMapViewPosition = mapView.getMapViewPosition();
mMapPosition = new MapPosition();
mJobs = new ArrayList<JobTile>();
mTiles = new MapTile[GLRenderer.CACHE_TILES];
mTilesSize = 0;
mUpdateCnt = 0;
tilesForUpload = 0;
mTilesForUpload = 0;
mUpdateSerial = 0;
mInitialized = false;
}
public void destroy() {
// there might be some leaks in here
// ... free pools
}
/**
* Update list of visible tiles and passes them to TileManager, when not
* available tiles are created and added to JobQueue (mapView.addJobs) for
@ -207,7 +159,7 @@ public class TileManager {
MapPosition mapPosition = mMapPosition;
float[] coords = mTileCoords;
changedPos = mMapViewPosition.getMapPosition(mapPosition, coords);
changedPos = mMapView.getMapViewPosition().getMapPosition(mapPosition, coords);
if (changedPos) {
mMapView.render();
@ -236,7 +188,7 @@ public class TileManager {
int remove = mTilesCount - GLRenderer.CACHE_TILES;
if (remove > CACHE_THRESHOLD ||
tilesForUpload > (MAX_TILES_IN_QUEUE + 10))
mTilesForUpload > MAX_TILES_IN_QUEUE)
limitCache(mapPosition, remove);
}
}
@ -244,15 +196,15 @@ public class TileManager {
// need to keep track of TileSets to clear on reset...
private static ArrayList<TileSet> mTileSets = new ArrayList<TileSet>(2);
public static TileSet getActiveTiles(TileSet td) {
public TileSet getActiveTiles(TileSet td) {
if (mCurrentTiles == null)
return td;
if (td != null && td.serial == mUpdateCnt)
if (td != null && td.serial == mUpdateSerial)
return td;
// dont flip new/currentTiles while copying
synchronized (tilelock) {
synchronized (mTilelock) {
MapTile[] newTiles = mCurrentTiles.tiles;
int cnt = mCurrentTiles.cnt;
@ -276,7 +228,7 @@ public class TileManager {
// copy newTiles to nextTiles
System.arraycopy(newTiles, 0, nextTiles, 0, cnt);
td.serial = mUpdateCnt;
td.serial = mUpdateSerial;
td.cnt = cnt;
}
@ -329,7 +281,7 @@ public class TileManager {
}
if (changed) {
synchronized (tilelock) {
synchronized (mTilelock) {
for (int i = 0, n = mNewTiles.cnt; i < n; i++)
newTiles[i].lock();
@ -340,7 +292,7 @@ public class TileManager {
mCurrentTiles = mNewTiles;
mNewTiles = tmp;
mUpdateCnt++;
mUpdateSerial++;
}
}
//Log.d(TAG, "tiles: " + mCurrentTiles.cnt + " added: " + mJobs.size());
@ -494,12 +446,19 @@ public class TileManager {
MapTile[] tiles = mTiles;
int size = mTilesSize;
// count tiles that have new data
mTilesForUpload = 0;
int newTileCnt = 0;
// remove tiles that were never loaded
for (int i = 0; i < size; i++) {
MapTile t = tiles[i];
if (t == null)
continue;
if (t.state == STATE_NEW_DATA)
newTileCnt++;
// make sure tile cannot be used by GL or MapWorker Thread
if ((t.state != 0) || t.isLocked()) {
continue;
@ -509,17 +468,17 @@ public class TileManager {
remove--;
}
if (remove > 10 || tilesForUpload > MAX_TILES_IN_QUEUE) {
if (remove > 10 || newTileCnt > MAX_TILES_IN_QUEUE) {
updateTileDistances(tiles, size, mapPosition);
TileDistanceSort.sort(tiles, 0, size);
// sorting also repacks the 'sparse' filled array
// so end of mTiles is at mTilesCount now
mTilesSize = size = mTilesCount;
size = mTilesSize = mTilesCount;
for (int i = 1; i < remove; i++) {
MapTile t = tiles[size - i];
for (int i = size - 1; i >= 0 && remove > 0; i--) {
MapTile t = tiles[i];
if (t.isLocked()) {
// dont remove tile used by GLRenderer, or somewhere else
Log.d(TAG, "limitCache: tile still locked " + t + " " + t.distance);
@ -533,26 +492,31 @@ public class TileManager {
Log.d(TAG, "limitCache: cancel loading " + t + " " + t.distance);
} else {
if (t.state == STATE_NEW_DATA)
tilesForUpload--;
newTileCnt--;
clearTile(t);
tiles[size - i] = null;
}
}
remove = (tilesForUpload - MAX_TILES_IN_QUEUE);
//Log.d(TAG, "cleanup load queue " + tilesForUpload + "/" + remove);
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--;
clearTile(t);
tiles[i] = null;
}
}
remove = (newTileCnt - MAX_TILES_IN_QUEUE) + 10;
//int r = remove;
for (int i = size - 1; i >= 0 && remove > 0; i--) {
MapTile t = tiles[i];
if (t != null && t.state == STATE_NEW_DATA) {
if (!t.isLocked()) {
clearTile(t);
tiles[i] = null;
remove--;
newTileCnt--;
}
}
}
mTilesForUpload += newTileCnt;
//Log.d(TAG, "cleanup load queue " + tilesForUpload + "/" + r + " - " + remove);
}
}
@ -581,14 +545,13 @@ public class TileManager {
}
tile.state = STATE_NEW_DATA;
mTilesForUpload++;
// locked means the tile is visible or referenced by
// a tile that might be visible.
if (tile.isLocked())
mMapView.render();
tilesForUpload++;
return true;
}
@ -598,4 +561,50 @@ public class TileManager {
mWidth = w;
mHeight = h;
}
private final ScanBox mScanBox = new ScanBox() {
@Override
public void setVisible(int y, int x1, int x2) {
MapTile[] tiles = mNewTiles.tiles;
int cnt = mNewTiles.cnt;
int max = tiles.length;
int xmax = 1 << mZoom;
for (int x = x1; x < x2; x++) {
MapTile tile = null;
if (cnt == max) {
Log.d(TAG, "reached maximum tiles " + max);
break;
}
// NOTE to myself: do not modify x!
int xx = x;
if (x < 0 || x >= xmax) {
// flip-around date line
if (x < 0)
xx = xmax + x;
else
xx = x - xmax;
if (xx < 0 || xx >= xmax)
continue;
}
// check if tile is already added
for (int i = 0; i < cnt; i++)
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
tile = tiles[i];
break;
}
if (tile == null) {
tile = addTile(xx, y, mZoom, 0);
tiles[cnt++] = tile;
}
}
mNewTiles.cnt = cnt;
}
};
}

View File

@ -23,7 +23,6 @@ import org.oscim.generator.JobTile;
import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLState;
import org.oscim.renderer.MapTile;
import org.oscim.renderer.TileManager;
import org.oscim.renderer.TileSet;
import org.oscim.renderer.layer.ExtrusionLayer;
import org.oscim.utils.FastMath;
@ -95,7 +94,7 @@ public class ExtrusionOverlay extends RenderOverlay {
}
int ready = 0;
mTileSet = TileManager.getActiveTiles(mTileSet);
mTileSet = mMapView.getTileManager().getActiveTiles(mTileSet);
MapTile[] tiles = mTileSet.tiles;
// FIXME just release tiles in this case
if (mAlpha == 0 || curPos.zoomLevel < 16) {
@ -337,7 +336,7 @@ public class ExtrusionOverlay extends RenderOverlay {
private final float _g = 0xe8;
private final float _b = 0xe6;
private final float _o = 55;
private final float _s = 25;
private final float _s = 20;
private final float _l = 14;
private float mAlpha = 1;
private final float[] mColor = {

View File

@ -19,7 +19,6 @@ import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.MapTile;
import org.oscim.renderer.TileManager;
import org.oscim.renderer.TileSet;
import org.oscim.renderer.layer.Layer;
import org.oscim.renderer.layer.Layers;
@ -165,7 +164,7 @@ public class TextOverlay extends BasicOverlay {
private final Layers mDebugLayer = null; //new Layers();
void updateLabels() {
mTiles = TileManager.getActiveTiles(mTiles);
mTiles = mMapView.getTileManager().getActiveTiles(mTiles);
// Log.d("...", "relabel " + mRerun + " " + x + " " + y);
if (mTiles.cnt == 0)

View File

@ -15,8 +15,6 @@
package org.oscim.renderer.overlays;
import java.util.HashMap;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.generator.JobTile;
@ -45,10 +43,9 @@ import android.graphics.Paint.Cap;
import android.opengl.GLES20;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.util.Log;
public class TextOverlayExp extends BasicOverlay {
private final static String TAG = TextOverlayExp.class.getName();
// private final static String TAG = TextOverlayExp.class.getName();
private TileSet mTileSet;
private LabelThread mThread;
@ -90,8 +87,6 @@ public class TextOverlayExp extends BasicOverlay {
}
}
private int mSerial;
public TextOverlayExp(MapView mapView) {
super(mapView);
@ -101,27 +96,26 @@ public class TextOverlayExp extends BasicOverlay {
mTmpPos = new MapPosition();
mThread = new LabelThread();
mThread.start();
mSerial = 0;
}
private HashMap<TextItem, PlacementItem> mItemMap;
class PlacementItem extends TextItem {
int tileX;
int tileY;
boolean isTileNeighbour(PlacementItem other) {
int dx = other.tileX - tileX;
if (dx > 1 || dx < -1)
return false;
int dy = other.tileY - tileY;
if (dy > 1 || dy < -1)
return false;
return true;
}
}
// private HashMap<TextItem, PlacementItem> mItemMap;
//
// class PlacementItem extends TextItem {
// int tileX;
// int tileY;
//
// boolean isTileNeighbour(PlacementItem other) {
// int dx = other.tileX - tileX;
// if (dx > 1 || dx < -1)
// return false;
//
// int dy = other.tileY - tileY;
// if (dy > 1 || dy < -1)
// return false;
//
// return true;
// }
// }
// local pool, avoids synchronized TextItem.get()/release()
private TextItem mPool;
@ -226,8 +220,6 @@ public class TextOverlayExp extends BasicOverlay {
if (mTileSet.cnt == 0)
return false;
mSerial++;
TextLayer tl = mTmpLayer;
mTmpLayer = null;
@ -269,7 +261,6 @@ public class TextOverlayExp extends BasicOverlay {
ll.line = new Line((Color.GREEN & 0xaaffffff), 1, Cap.BUTT);
ll.width = 2;
}
int added = 0;
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
@ -391,12 +382,7 @@ public class TextOverlayExp extends BasicOverlay {
}
}
}
int count = 0;
for (TextItem ti = tl.labels; ti != null; ti = ti.next) {
count++;
//ti.active = mSerial;
// scale back to fixed zoom-level. could be done in setMatrix
ti.x /= scale;
ti.y /= scale;
@ -430,9 +416,6 @@ public class TextOverlayExp extends BasicOverlay {
tl.setScale(scale);
tl.prepare();
if (count == 0)
Log.d(TAG, "> no labels: " + count + " " + added);
//TextItem.printPool();
//Log.d(TAG, "new labels: " + count);
@ -487,21 +470,18 @@ public class TextOverlayExp extends BasicOverlay {
@Override
public void compile() {
int newSize = layers.getSize();
if (newSize == 0)
Log.d(TAG, "text layer size " + newSize);
//if (newSize == 0)
// Log.d(TAG, "text layer size " + newSize);
if (newSize == 0) {
BufferObject.release(vbo);
vbo = null;
//BufferObject.release(vbo);
//vbo = null;
isReady = false;
return;
}
if (vbo == null) {
vbo = BufferObject.get(0);
if (vbo == null)
return;
}
if (newSize > 0) {
@ -552,6 +532,9 @@ public class TextOverlayExp extends BasicOverlay {
private boolean mHolding;
/**
* @param enable layer updates
*/
public synchronized void hold(boolean enable) {
// mHolding = enable;
// if (!enable && !mRun) {

View File

@ -662,6 +662,10 @@ public class MapView extends RelativeLayout {
return mOverlayManager;
}
public TileManager getTileManager() {
return mTileManager;
}
public BoundingBox getBoundingBox() {
return mMapViewPosition.getViewBox();
}