diff --git a/vtm/src/org/oscim/layers/tile/JobQueue.java b/vtm/src/org/oscim/layers/tile/JobQueue.java index a68c9c71..8a9edb61 100644 --- a/vtm/src/org/oscim/layers/tile/JobQueue.java +++ b/vtm/src/org/oscim/layers/tile/JobQueue.java @@ -16,6 +16,7 @@ */ package org.oscim.layers.tile; +import static org.oscim.layers.tile.MapTile.State.CANCEL; import static org.oscim.layers.tile.MapTile.State.LOADING; import static org.oscim.layers.tile.MapTile.State.NONE; @@ -37,9 +38,6 @@ public class JobQueue { * the jobs to be added to this queue. */ public synchronized void setJobs(MapTile[] tiles) { - for (MapTile t : tiles) - t.state = LOADING; - mJobs = tiles; mCurrentJob = 0; } @@ -55,12 +53,12 @@ public class JobQueue { MapTile[] tiles = mJobs; for (int i = mCurrentJob, n = mJobs.length; i < n; i++) { - - if (tiles[i].state == LOADING) - tiles[i].state = NONE; - else - log.debug("wrong tile in queue {} {}", tiles[i], tiles[i].state); - + MapTile t = tiles[i]; + if (t.state(LOADING | CANCEL)) { + t.setState(NONE); + } else { + log.error("Wrong tile in queue {} {}", t, t.state()); + } tiles[i] = null; } mCurrentJob = 0; diff --git a/vtm/src/org/oscim/layers/tile/MapTile.java b/vtm/src/org/oscim/layers/tile/MapTile.java index 3f42913d..2267dd02 100644 --- a/vtm/src/org/oscim/layers/tile/MapTile.java +++ b/vtm/src/org/oscim/layers/tile/MapTile.java @@ -16,9 +16,13 @@ */ package org.oscim.layers.tile; +import static org.oscim.layers.tile.MapTile.State.CANCEL; import static org.oscim.layers.tile.MapTile.State.DEADBEEF; +import static org.oscim.layers.tile.MapTile.State.LOADING; import static org.oscim.layers.tile.MapTile.State.NEW_DATA; +import static org.oscim.layers.tile.MapTile.State.NONE; import static org.oscim.layers.tile.MapTile.State.READY; +import static org.oscim.layers.tile.MapTile.State.TIMEOUT; import org.oscim.core.Tile; import org.oscim.layers.tile.vector.VectorTileLoader; @@ -44,34 +48,38 @@ public class MapTile extends Tile { } public static final class State { - public final static byte NONE = 0; + public final static byte NONE = (1 << 0); /** * STATE_LOADING means the tile is about to be loaded / loading. * Tile belongs to TileLoader thread. */ - public final static byte LOADING = (1 << 0); + public final static byte LOADING = (1 << 1); /** * STATE_NEW_DATA: tile data is prepared for rendering. * While 'locked' it belongs to GL Thread. */ - public final static byte NEW_DATA = (1 << 1); + public final static byte NEW_DATA = (1 << 2); /** * STATE_READY: tile data is uploaded to GL. * While 'locked' it belongs to GL Thread. */ - public final static byte READY = (1 << 2); + public final static byte READY = (1 << 3); /** * STATE_CANCEL: tile is removed from TileManager, * but may still be processed by TileLoader. */ - public final static byte CANCEL = (1 << 3); + public final static byte CANCEL = (1 << 4); - public final static byte DEADBEEF = (1 << 4); + public final static byte TIMEOUT = (1 << 5); + /** + * Dont touch if you find some. + */ + public final static byte DEADBEEF = (1 << 6); } public final static int PROXY_CHILD00 = (1 << 0); @@ -83,7 +91,7 @@ public class MapTile extends Tile { public final static int PROXY_HOLDER = (1 << 6); /** Tile state */ - byte state; + byte state = State.NONE; /** * absolute tile coordinates: tileX,Y / Math.pow(2, zoomLevel) @@ -176,6 +184,11 @@ public class MapTile extends Tile { * used. This function should only be called through {@link TileManager} */ void lock() { + if (state == DEADBEEF) { + log.debug("Locking dead tile {}", this); + return; + } + if (locked++ > 0) return; @@ -218,6 +231,12 @@ public class MapTile extends Tile { if (--locked > 0) return; + if (state == DEADBEEF) { + log.debug("Unlock dead tile {}", this); + clear(); + return; + } + TileNode parent = node.parent; if ((proxy & PROXY_PARENT) != 0) parent.item.refs--; @@ -259,7 +278,7 @@ public class MapTile extends Tile { data.dispose(); data = data.next; } - state = DEADBEEF; + state = NONE; } /** @@ -367,4 +386,75 @@ public class MapTile extends Tile { return p; } + + public String state() { + switch (state) { + case State.NONE: + return "None"; + case State.LOADING: + return "Loading"; + case State.NEW_DATA: + return "Data"; + case State.READY: + return "Ready"; + case State.CANCEL: + return "Cancel"; + case State.TIMEOUT: + return "Timeout"; + case State.DEADBEEF: + return "Dead"; + } + return ""; + } + + void setState(byte newState) { + if (state == newState) + return; + + switch (newState) { + case NONE: + if (state(LOADING | CANCEL)) { + state = newState; + return; + } + throw new IllegalStateException("None" + + " <= " + state() + " " + this); + case LOADING: + if (state == NONE) { + state = newState; + return; + } + throw new IllegalStateException("Loading" + + " <= " + state() + " " + this); + case NEW_DATA: + if (state == LOADING) { + state = newState; + return; + } + throw new IllegalStateException("NewData" + + " <= " + state() + " " + this); + + case READY: + if (state == NEW_DATA) { + state = newState; + return; + } + throw new IllegalStateException("Ready" + + " <= " + state() + " " + this); + + case CANCEL: + if (state == LOADING) { + state = newState; + return; + } + throw new IllegalStateException("Cancel" + + " <= " + state() + " " + this); + case TIMEOUT: + // TODO + break; + case DEADBEEF: + state = newState; + break; + } + } } diff --git a/vtm/src/org/oscim/layers/tile/TileManager.java b/vtm/src/org/oscim/layers/tile/TileManager.java index 1fdd7ef6..96d111ed 100644 --- a/vtm/src/org/oscim/layers/tile/TileManager.java +++ b/vtm/src/org/oscim/layers/tile/TileManager.java @@ -21,6 +21,7 @@ import static org.oscim.layers.tile.MapTile.State.CANCEL; import static org.oscim.layers.tile.MapTile.State.DEADBEEF; import static org.oscim.layers.tile.MapTile.State.LOADING; import static org.oscim.layers.tile.MapTile.State.NEW_DATA; +import static org.oscim.layers.tile.MapTile.State.NONE; import static org.oscim.layers.tile.MapTile.State.READY; import java.util.ArrayList; @@ -65,7 +66,6 @@ public class TileManager { /** cache limit threshold */ private static final int CACHE_THRESHOLD = 25; private static final int CACHE_CLEAR_THRESHOLD = 10; - private static final int QUEUE_CLEAR_THRESHOLD = 10; private final Map mMap; private final Viewport mViewport; @@ -77,10 +77,10 @@ public class TileManager { private int mTilesCount; /** current end position in mTiles */ - private int mTilesSize; + private int mTilesEnd; /** counter for tiles with new data not yet loaded to GL */ - private int mTilesForUpload; + private int mTilesToUpload; /** new tile jobs for MapWorkers */ private final ArrayList mJobs; @@ -112,7 +112,7 @@ public class TileManager { @Override public void removeItem(MapTile t) { if (t.node == null) - throw new IllegalStateException("already removed: " + t); + throw new IllegalStateException("Already removed: " + t); super.remove(t.node); t.node.item = null; @@ -149,8 +149,8 @@ public class TileManager { mJobs = new ArrayList(); mTiles = new MapTile[mCacheLimit]; - mTilesSize = 0; - mTilesForUpload = 0; + mTilesEnd = 0; + mTilesToUpload = 0; mUpdateSerial = 0; } @@ -165,17 +165,28 @@ public class TileManager { } public void init() { + if (mCurrentTiles != null) + mCurrentTiles.releaseTiles(); /* pass VBOs and VertexItems back to pools */ - for (int i = 0; i < mTilesSize; i++) { - if (mTiles[i] == null) + for (int i = 0; i < mTilesEnd; i++) { + MapTile t = mTiles[i]; + if (t == null) continue; - removeFromCache(mTiles[i]); - mTiles[i].state = CANCEL; + + if (!t.isLocked()) { + //log.debug("init clear {} {}", t, t.state()); + t.clear(); + } + mIndex.removeItem(t); + + /* in case the tile is still loading: + * clear when returned from loader */ + t.setState(DEADBEEF); } /* clear references to cached MapTiles */ Arrays.fill(mTiles, null); - mTilesSize = 0; + mTilesEnd = 0; mTilesCount = 0; /* set up TileSet large enough to hold current tiles */ @@ -198,6 +209,7 @@ public class TileManager { public boolean update(MapPosition pos) { // FIXME cant expect init to be called otherwise + // Should use some onLayerAttached callback instead. if (mNewTiles == null || mNewTiles.tiles.length == 0) { mPrevZoomlevel = pos.zoomLevel; init(); @@ -319,17 +331,19 @@ public class TileManager { mCacheReduce += 10; if (dbg) log.debug("reduce cache {}", (mCacheLimit - mCacheReduce)); - } else + } else { mCacheReduce = 0; + } } /* limit cache items */ int remove = mTilesCount - (mCacheLimit - mCacheReduce); - if (remove > CACHE_THRESHOLD || - mTilesForUpload > MAX_TILES_IN_QUEUE) - limitCache(pos, remove); - + if (remove > CACHE_THRESHOLD || mTilesToUpload > MAX_TILES_IN_QUEUE) { + synchronized (mTilelock) { + limitCache(pos, remove); + } + } return true; } @@ -379,9 +393,11 @@ public class TileManager { if (tile == null) { TileNode n = mIndex.add(x, y, zoomLevel); tile = n.item = new MapTile(n, x, y, zoomLevel); + tile.setState(LOADING); mJobs.add(tile); addToCache(tile); } else if (!tile.isActive()) { + tile.setState(LOADING); mJobs.add(tile); } @@ -393,10 +409,10 @@ public class TileManager { p = n.item = new MapTile(n, x >> 1, y >> 1, zoomLevel - 1); addToCache(p); /* this prevents to add tile twice to queue */ - p.state = LOADING; + p.setState(LOADING); mJobs.add(p); } else if (!p.isActive()) { - p.state = LOADING; + p.setState(LOADING); mJobs.add(p); } } @@ -405,133 +421,139 @@ public class TileManager { private void addToCache(MapTile tile) { - if (mTilesSize == mTiles.length) { - if (mTilesSize > mTilesCount) { - TileDistanceSort.sort(mTiles, 0, mTilesSize); + if (mTilesEnd == mTiles.length) { + if (mTilesEnd > mTilesCount) { + TileDistanceSort.sort(mTiles, 0, mTilesEnd); /* sorting also repacks the 'sparse' filled array * so end of mTiles is at mTilesCount now */ - mTilesSize = mTilesCount; + mTilesEnd = mTilesCount; } - if (mTilesSize == mTiles.length) { - log.debug("realloc tiles {}", mTilesSize); + if (mTilesEnd == mTiles.length) { + log.debug("realloc tiles {}", mTilesEnd); MapTile[] tmp = new MapTile[mTiles.length + 20]; System.arraycopy(mTiles, 0, tmp, 0, mTilesCount); mTiles = tmp; } } - mTiles[mTilesSize++] = tile; + mTiles[mTilesEnd++] = tile; mTilesCount++; } - private void removeFromCache(MapTile t) { + private boolean removeFromCache(MapTile t) { + /* TODO check valid states here:When in CANCEL state tile belongs to + * TileLoader thread, defer clearing to jobCompleted() */ + + if (dbg) + log.debug("remove from cache {} {} {}", + t, t.state(), t.isLocked()); + + if (t.isLocked()) + return false; + if (t.state(NEW_DATA | READY)) events.fire(TILE_REMOVED, t); - if (dbg) - log.debug("remove from cache {} {} {}", t, t.state, t.isLocked()); - - /* When in CANCEL state tile belongs to TileLoader thread, - * defer clearing to jobCompleted() */ - if (t.state != CANCEL) - t.clear(); + t.clear(); mIndex.removeItem(t); - mTilesCount--; + return true; } private void limitCache(MapPosition pos, int remove) { 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++) { + for (int i = 0; i < mTilesEnd; i++) { MapTile t = tiles[i]; if (t == null) continue; - if (t.state == NEW_DATA) + if (t.state(NEW_DATA)) newTileCnt++; - if (t.state == DEADBEEF) { - //log.debug("found DEADBEEF {}", t); + if (t.state(DEADBEEF)) { + log.debug("found DEADBEEF {}", t); + t.clear(); tiles[i] = null; - mTilesCount--; - continue; - } - /* make sure tile cannot be used by GL or MapWorker Thread */ - if ((t.state != 0) || t.isLocked()) { continue; } - /* empty tile */ - removeFromCache(t); - tiles[i] = null; - remove--; + /* make sure tile cannot be used by GL or MapWorker Thread */ + if (t.state(NONE) && removeFromCache(t)) { + tiles[i] = null; + remove--; + } } if ((remove < CACHE_CLEAR_THRESHOLD) && (newTileCnt < MAX_TILES_IN_QUEUE)) return; - updateDistances(tiles, size, pos); - TileDistanceSort.sort(tiles, 0, size); + updateDistances(tiles, mTilesEnd, pos); + TileDistanceSort.sort(tiles, 0, mTilesEnd); /* sorting also repacks the 'sparse' filled array * so end of mTiles is at mTilesCount now */ - size = mTilesSize = mTilesCount; - - // log.debug("remove:" + remove + " new:" + newTileCnt); - // log.debug("cur: " + mapPosition); + mTilesEnd = mTilesCount; /* start with farest away tile */ - for (int i = size - 1; i >= 0 && remove > 0; i--) { + for (int i = mTilesCount - 1; i >= 0 && remove > 0; i--) { MapTile t = tiles[i]; /* dont remove tile used by TileRenderer, or somewhere else * try again in next run. */ if (t.isLocked()) { if (dbg) - log.debug("{} locked (state={}, d={})", t, t.state, t.distance); + log.debug("{} locked (state={}, d={})", + t, t.state(), t.distance); + continue; + } + + if (t.state(CANCEL)) { continue; } /* cancel loading of tiles that should not even be cached */ - if (t.state == LOADING) { - t.state = CANCEL; + if (t.state(LOADING)) { + t.setState(CANCEL); if (dbg) log.debug("{} canceled (d={})", t, t.distance); + continue; } /* clear new and unused tile */ - if (t.state == NEW_DATA) { + if (t.state(NEW_DATA)) { newTileCnt--; if (dbg) log.debug("{} unused (d=({})", t, t.distance); } - removeFromCache(t); - tiles[i] = null; - remove--; - } + if (!t.state(READY | NEW_DATA)) { + log.error("stuff that should be here! {} {}", t, t.state()); + } - remove = (newTileCnt - MAX_TILES_IN_QUEUE) + QUEUE_CLEAR_THRESHOLD; - for (int i = size - 1; i >= 0 && remove > 0; i--) { - MapTile t = tiles[i]; - if ((t != null) && (t.state == NEW_DATA) && !t.isLocked()) { - removeFromCache(t); + if (removeFromCache(t)) { tiles[i] = null; remove--; - newTileCnt--; } } - mTilesForUpload += newTileCnt; + for (int i = mTilesCount - 1; i >= 0 && newTileCnt > MAX_TILES_IN_QUEUE; i--) { + MapTile t = tiles[i]; + if ((t != null) && (t.state(NEW_DATA))) { + if (removeFromCache(t)) { + tiles[i] = null; + newTileCnt--; + } + } + } + + mTilesToUpload = newTileCnt; } /** @@ -563,21 +585,23 @@ public class TileManager { @Override public void run() { - if (success && tile.state != CANCEL) { - tile.state = NEW_DATA; + if (success && tile.state(LOADING)) { + tile.setState(NEW_DATA); events.fire(TILE_LOADED, tile); - - mTilesForUpload++; - //log.debug("loading {}: ready", tile); + mTilesToUpload++; return; } - log.debug("loading {}: {}", tile, - success ? "canceled" - : "failed"); + // TODO use mMap.update(true) to retry tile loading? + log.debug("Load: {} {} state:{}", + tile, success ? "success" : "failed", + tile.state()); - if (tile.state == LOADING) - mIndex.removeItem(tile); + /* got orphaned tile */ + if (tile.state(DEADBEEF)) { + tile.clear(); + return; + } tile.clear(); } diff --git a/vtm/src/org/oscim/layers/tile/TileRenderer.java b/vtm/src/org/oscim/layers/tile/TileRenderer.java index 2687c6e2..f1fe46ef 100644 --- a/vtm/src/org/oscim/layers/tile/TileRenderer.java +++ b/vtm/src/org/oscim/layers/tile/TileRenderer.java @@ -20,7 +20,6 @@ import static org.oscim.layers.tile.MapTile.PROXY_PARENT; import static org.oscim.layers.tile.MapTile.State.NEW_DATA; import static org.oscim.layers.tile.MapTile.State.READY; -import org.oscim.core.MapPosition; import org.oscim.layers.tile.MapTile.TileNode; import org.oscim.renderer.BufferObject; import org.oscim.renderer.GLViewport; @@ -79,50 +78,61 @@ public abstract class TileRenderer extends LayerRenderer { */ @Override public synchronized void update(GLViewport v) { + /* count placeholder tiles */ if (mAlpha == 0) { mDrawTiles.releaseTiles(); + setReady(false); return; } - /* get current tiles to draw */ - boolean tilesChanged; - synchronized (tilelock) { - tilesChanged = mTileManager.getActiveTiles(mDrawTiles); - } - - if (mDrawTiles.cnt == 0) - return; - /* keep constant while rendering frame */ mLayerAlpha = mAlpha; mOverdrawColor = mOverdraw; - int tileCnt = mDrawTiles.cnt; - MapTile[] tiles = mDrawTiles.tiles; + /* get current tiles to draw */ + synchronized (tilelock) { + boolean tilesChanged = mTileManager.getActiveTiles(mDrawTiles); - if (tilesChanged || v.changed()) { - updateTileVisibility(v.pos, v.plane); + if (mDrawTiles.cnt == 0) { + setReady(false); + mProxyTileCnt = 0; + return; + } + + /* update isVisible flag true for tiles that intersect view */ + if (tilesChanged || v.changed()) { + + /* lock tiles while updating isVisible state */ + mProxyTileCnt = 0; + + MapTile[] tiles = mDrawTiles.tiles; + int tileZoom = tiles[0].zoomLevel; + + for (int i = 0; i < mDrawTiles.cnt; i++) + tiles[i].isVisible = false; + + /* no renderable tile can be locked at this point */ + if (tileZoom > v.pos.zoomLevel + 2 || tileZoom < v.pos.zoomLevel - 4) { + return; + } + + /* check visibile tiles */ + mScanBox.scan(v.pos.x, v.pos.y, v.pos.scale, tileZoom, v.plane); + } } - - tileCnt += mProxyTileCnt; - /* prepare tiles for rendering */ - if (compileTileLayers(tiles, tileCnt) > 0) { + if (compileTileLayers(mDrawTiles.tiles, mDrawTiles.cnt + mProxyTileCnt) > 0) { mUploadSerial++; BufferObject.checkBufferUsage(false); } - } - - @Override - public void render(GLViewport v) { - /* render in update() so that tiles cannot vanish in between. */ + setReady(true); } public void clearTiles() { /* Clear all references to MapTiles as all current * tiles will also be removed from TileManager. */ - //mDrawTiles = new TileSet(); + mDrawTiles.releaseTiles(); mDrawTiles.tiles = new MapTile[1]; mDrawTiles.cnt = 0; } @@ -137,17 +147,17 @@ public abstract class TileRenderer extends LayerRenderer { if (!tile.isVisible) continue; - if (tile.state == READY) + if (tile.state(READY)) continue; - if (tile.state == NEW_DATA) { + if (tile.state(NEW_DATA)) { uploadCnt += uploadTileData(tile); continue; } /* load tile that is referenced by this holder */ MapTile proxy = tile.holder; - if (proxy != null && proxy.state == NEW_DATA) { + if (proxy != null && proxy.state(NEW_DATA)) { uploadCnt += uploadTileData(proxy); tile.state = proxy.state; continue; @@ -174,7 +184,7 @@ public abstract class TileRenderer extends LayerRenderer { } private static int uploadTileData(MapTile tile) { - tile.state = READY; + tile.setState(READY); RenderBuckets buckets = tile.getBuckets(); /* tile might only contain label layers */ @@ -191,30 +201,6 @@ public abstract class TileRenderer extends LayerRenderer { private final Object tilelock = new Object(); - /** set tile isVisible flag true for tiles that intersect view */ - private void updateTileVisibility(MapPosition pos, float[] box) { - - /* lock tiles while updating isVisible state */ - synchronized (tilelock) { - MapTile[] tiles = mDrawTiles.tiles; - - int tileZoom = tiles[0].zoomLevel; - - for (int i = 0; i < mDrawTiles.cnt; i++) - tiles[i].isVisible = false; - - if (tileZoom > pos.zoomLevel + 2 || tileZoom < pos.zoomLevel - 4) { - //log.debug("skip: zoomlevel diff " + (tileZoom - pos.zoomLevel)); - return; - } - /* count placeholder tiles */ - mProxyTileCnt = 0; - - /* check visibile tiles */ - mScanBox.scan(pos.x, pos.y, pos.scale, tileZoom, box); - } - } - /** * Update tileSet with currently visible tiles get a TileSet of currently * visible tiles @@ -248,7 +234,7 @@ public abstract class TileRenderer extends LayerRenderer { tileSet.cnt = 0; for (int i = 0; i < cnt; i++) { MapTile t = newTiles[i]; - if (t.isVisible && t.state == READY) { + if (t.isVisible && t.state(READY)) { t.lock(); tileSet.tiles[tileSet.cnt++] = t; } diff --git a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java index 45704a0c..0b163617 100644 --- a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java +++ b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java @@ -45,8 +45,7 @@ public class VectorTileRenderer extends TileRenderer { protected int mDrawSerial; @Override - public synchronized void update(GLViewport v) { - super.update(v); + public synchronized void render(GLViewport v) { /* discard depth projection from tilt, depth buffer * is used for clipping */ @@ -67,8 +66,8 @@ public class VectorTileRenderer extends TileRenderer { for (int i = 0; i < tileCnt; i++) { MapTile t = tiles[i]; - // TODO check if proxies are actually available - if (t.isVisible && t.state != READY) { + + if (t.isVisible && !t.state(READY)) { GL.glDepthMask(true); GL.glClear(GL20.GL_DEPTH_BUFFER_BIT); @@ -87,7 +86,7 @@ public class VectorTileRenderer extends TileRenderer { /* draw visible tiles */ for (int i = 0; i < tileCnt; i++) { MapTile t = tiles[i]; - if (t.isVisible && t.state == READY) + if (t.isVisible && t.state(READY)) drawTile(t, v, 0); } @@ -155,8 +154,10 @@ public class VectorTileRenderer extends TileRenderer { ? tile.getBuckets() : tile.holder.getBuckets(); - if (buckets == null || buckets.vbo == null) + if (buckets == null || buckets.vbo == null) { + //log.debug("{} no buckets!", tile); return; + } MapPosition pos = v.pos; /* place tile relative to map position */ diff --git a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLayer.java b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLayer.java index e80ea636..db9ac80b 100644 --- a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLayer.java +++ b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLayer.java @@ -33,7 +33,7 @@ public class BitmapTileLayer extends TileLayer { protected static final Logger log = LoggerFactory.getLogger(BitmapTileLayer.class); - private final static int CACHE_LIMIT = 20; + private final static int CACHE_LIMIT = 40; protected final TileSource mTileSource; @@ -110,7 +110,7 @@ public class BitmapTileLayer extends TileLayer { pool.clear(); } - final static int POOL_FILL = 40; + final static int POOL_FILL = 20; /** pool shared by TextLayers */ final TexturePool pool = new TexturePool(POOL_FILL) { diff --git a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java index c1f0b6eb..ff1074eb 100644 --- a/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java +++ b/vtm/src/org/oscim/layers/tile/bitmap/BitmapTileLoader.java @@ -16,7 +16,7 @@ */ package org.oscim.layers.tile.bitmap; -import static org.oscim.layers.tile.MapTile.State.CANCEL; +import static org.oscim.layers.tile.MapTile.State.LOADING; import org.oscim.backend.canvas.Bitmap; import org.oscim.core.Tile; @@ -55,23 +55,26 @@ public class BitmapTileLoader extends TileLoader { @Override public void setTileImage(Bitmap bitmap) { - if (isCanceled() || mTile.state(CANCEL)) + if (isCanceled() || !mTile.state(LOADING)) { + bitmap.recycle(); return; + } BitmapBucket l = new BitmapBucket(false); l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE, mLayer.pool); - RenderBuckets b = new RenderBuckets(); - b.set(l); - mTile.data = b; + RenderBuckets buckets = new RenderBuckets(); + buckets.set(l); + mTile.data = buckets; } @Override public void dispose() { + mTileDataSource.cancel(); } @Override public void cancel() { + mTileDataSource.cancel(); } - } diff --git a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java index f8135be7..c676c31c 100644 --- a/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java +++ b/vtm/src/org/oscim/layers/tile/vector/VectorTileLoader.java @@ -16,7 +16,7 @@ */ package org.oscim.layers.tile.vector; -import static org.oscim.layers.tile.MapTile.State.CANCEL; +import static org.oscim.layers.tile.MapTile.State.LOADING; import org.oscim.core.GeometryBuffer.GeometryType; import org.oscim.core.MapElement; @@ -134,14 +134,15 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac @Override public void completed(QueryResult result) { - mTileLayer.callHooksComplete(mTile, result == QueryResult.SUCCESS); + boolean ok = (result == QueryResult.SUCCESS); + + mTileLayer.callHooksComplete(mTile, ok); /* finish buckets- tessellate and cleanup on worker-thread */ mBuckets.prepare(); + clearState(); super.completed(result); - - clearState(); } protected static int getValidLayer(int layer) { @@ -180,7 +181,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac @Override public void process(MapElement element) { - if (isCanceled() || mTile.state(CANCEL)) + if (isCanceled() || !mTile.state(LOADING)) return; if (mTileLayer.callProcessHooks(mTile, mBuckets, element))