keep tile loading state in JobTile.state

This commit is contained in:
Hannes Janetzek 2012-12-29 23:34:48 +01:00
parent 60637f7440
commit a8b25d07ad
6 changed files with 137 additions and 68 deletions

View File

@ -41,7 +41,8 @@ public class JobQueue {
for (int i = 0, n = tiles.size(); i < n; i++) { for (int i = 0, n = tiles.size(); i < n; i++) {
JobTile tile = tiles.get(i); JobTile tile = tiles.get(i);
tile.isLoading = true; //tile.isLoading = true;
tile.state = JobTile.STATE_LOADING;
mPriorityQueue.offer(tile); mPriorityQueue.offer(tile);
} }
} }
@ -50,10 +51,10 @@ public class JobQueue {
* Removes all jobs from this queue. * Removes all jobs from this queue.
*/ */
public synchronized void clear() { public synchronized void clear() {
JobTile t; JobTile t;
while ((t = mPriorityQueue.poll()) != null) while ((t = mPriorityQueue.poll()) != null)
t.isLoading = false; t.state = JobTile.STATE_NONE;
//t.isLoading = false;
mPriorityQueue.clear(); mPriorityQueue.clear();
} }

View File

@ -16,10 +16,13 @@ package org.oscim.generator;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import android.util.Log;
/** /**
* *
*/ */
public class JobTile extends Tile implements Comparable<JobTile> { public class JobTile extends Tile implements Comparable<JobTile> {
private final static String TAG = JobTile.class.getName();
// public final static int LOADING = 1; // public final static int LOADING = 1;
// public final static int NEWDATA = 1 << 1; // public final static int NEWDATA = 1 << 1;
// public final static int READY = 1 << 2; // public final static int READY = 1 << 2;
@ -27,10 +30,27 @@ public class JobTile extends Tile implements Comparable<JobTile> {
// public final static int CANCELED = 1 << 3; // public final static int CANCELED = 1 << 3;
// public int state; // public int state;
public final static int STATE_NONE = 0;
public final static int STATE_LOADING = 1 << 0;
public final static int STATE_NEW_DATA = 1 << 1;
public final static int STATE_READY = 1 << 2;
public void clearState() {
state = STATE_NONE;
}
public void setLoading() {
if (state != STATE_NONE)
Log.d(TAG, "wrong state: " + state);
state = STATE_LOADING;
}
/** /**
* tile is in JobQueue * tile is in JobQueue
*/ */
public boolean isLoading; //public boolean isLoading;
public byte state;
/** /**
* distance from map center. * distance from map center.

View File

@ -21,6 +21,8 @@ import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
import static android.opengl.GLES20.GL_ONE; import static android.opengl.GLES20.GL_ONE;
import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA; import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA;
import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL; import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL;
import static org.oscim.generator.JobTile.STATE_NEW_DATA;
import static org.oscim.generator.JobTile.STATE_READY;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
@ -166,6 +168,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
holder = new MapTile(x, y, mZoom); holder = new MapTile(x, y, mZoom);
holder.isVisible = true; holder.isVisible = true;
holder.holder = tile; holder.holder = tile;
tile.isVisible = true;
tiles[cnt + mHolderCount++] = holder; tiles[cnt + mHolderCount++] = holder;
} }
} }
@ -281,20 +284,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return true; return true;
} }
private static boolean uploadTileData(MapTile tile) { private static void uploadTileData(MapTile tile) {
if (tile.layers != null) { if (tile.layers == null) {
tile.isReady = uploadLayers(tile.layers, tile.vbo, true); BufferObject.release(tile.vbo);
tile.vbo = null;
if (!tile.isReady) { } else if (!uploadLayers(tile.layers, tile.vbo, true)) {
Log.d(TAG, "uploadTileData " + tile + " is empty!"); Log.d(TAG, "uploadTileData " + tile + " failed!");
tile.layers.clear(); tile.layers.clear();
tile.layers = null; tile.layers = null;
BufferObject.release(tile.vbo);
tile.vbo = null;
} }
}
tile.newData = false;
// Log.d(TAG, "uploaded " + tile.isReady + " " + tile);
return tile.isReady; tile.state = STATE_READY;
} }
private static boolean uploadOverlayData(RenderOverlay renderOverlay) { private static boolean uploadOverlayData(RenderOverlay renderOverlay) {
@ -307,10 +309,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return renderOverlay.isReady; return renderOverlay.isReady;
} }
private static void checkBufferUsage() { private static void checkBufferUsage(boolean force) {
// try to clear some unused vbo when exceding limit // try to clear some unused vbo when exceding limit
if (mBufferMemoryUsage < LIMIT_BUFFERS) { if (!force && mBufferMemoryUsage < LIMIT_BUFFERS) {
if (CACHE_TILES < CACHE_TILES_MAX) if (CACHE_TILES < CACHE_TILES_MAX)
CACHE_TILES += 50; CACHE_TILES += 50;
return; return;
@ -457,23 +459,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!tile.isVisible) if (!tile.isVisible)
continue; continue;
if (tile.newData) { if (tile.state == STATE_NEW_DATA) {
uploadTileData(tile); uploadTileData(tile);
continue; continue;
} }
if (tile.holder != null) { if (tile.holder != null) {
// load tile that is referenced by this holder // load tile that is referenced by this holder
if (tile.holder.newData) if (tile.holder.state == STATE_NEW_DATA)
uploadTileData(tile.holder); uploadTileData(tile.holder);
tile.isReady = tile.holder.isReady; tile.state = tile.holder.state;
} else if (!tile.isReady) { } else if (tile.state != STATE_READY) {
// check near relatives than can serve as proxy // check near relatives than can serve as proxy
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
MapTile rel = tile.rel.parent.tile; MapTile rel = tile.rel.parent.tile;
if (rel.newData) if (rel.state == STATE_NEW_DATA)
uploadTileData(rel); uploadTileData(rel);
continue; continue;
@ -483,14 +485,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
continue; continue;
MapTile rel = tile.rel.child[c].tile; MapTile rel = tile.rel.child[c].tile;
if (rel != null && rel.newData) if (rel != null && rel.state == STATE_NEW_DATA)
uploadTileData(rel); uploadTileData(rel);
} }
} }
} }
if (uploadCnt > 0) if (uploadCnt > 0)
checkBufferUsage(); checkBufferUsage(false);
tilesChanged |= (uploadCnt > 0); tilesChanged |= (uploadCnt > 0);
@ -507,7 +509,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t.isVisible && t.isReady) if (t.isVisible && t.state == STATE_READY)
drawTile(t); drawTile(t);
} }
@ -517,7 +519,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// TODO draw proxies for placeholder... // TODO draw proxies for placeholder...
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t.isVisible && !t.isReady && (t.holder == null)) if (t.isVisible && (t.state != STATE_READY) && (t.holder == null))
drawProxyTile(t); drawProxyTile(t);
} }
@ -577,6 +579,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mapPosition.viewMatrix, 0); mapPosition.viewMatrix, 0);
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1); PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
} }
if (GlUtils.checkGlOutOfMemory("finish")) {
checkBufferUsage(true);
// TODO also throw out some textures etc
}
} }
// used to not draw a tile twice per frame. // used to not draw a tile twice per frame.
@ -598,6 +605,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (tile.holder != null) if (tile.holder != null)
tile = tile.holder; tile = tile.holder;
if (tile.layers == null)
return;
GLES20.glPolygonOffset(0, mDrawCount++); GLES20.glPolygonOffset(0, mDrawCount++);
// seems there are not infinite offset units possible // seems there are not infinite offset units possible
@ -652,7 +662,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
MapTile c = tile.rel.child[i].tile; MapTile c = tile.rel.child[i].tile;
if (c.isReady) { if (c.state == STATE_READY) {
drawTile(c); drawTile(c);
drawn++; drawn++;
} }
@ -669,7 +679,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!drawProxyChild(tile)) { if (!drawProxyChild(tile)) {
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
MapTile t = tile.rel.parent.tile; MapTile t = tile.rel.parent.tile;
if (t.isReady) { if (t.state == STATE_READY) {
drawTile(t); drawTile(t);
drawn = true; drawn = true;
} }
@ -677,7 +687,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) { if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
MapTile t = tile.rel.parent.parent.tile; MapTile t = tile.rel.parent.parent.tile;
if (t.isReady) if (t.state == STATE_READY)
drawTile(t); drawTile(t);
} }
@ -686,14 +696,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// prefer drawing parent // prefer drawing parent
MapTile t = tile.rel.parent.tile; MapTile t = tile.rel.parent.tile;
if (t != null && t.isReady) { if (t != null && t.state == STATE_READY) {
drawTile(t); drawTile(t);
} else if (!drawProxyChild(tile)) { } else if (!drawProxyChild(tile)) {
if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) { if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
t = tile.rel.parent.parent.tile; t = tile.rel.parent.parent.tile;
if (t.isReady) if (t.state == STATE_READY)
drawTile(t); drawTile(t);
} }
} }
@ -789,4 +799,33 @@ public class GLRenderer implements GLSurfaceView.Renderer {
void clearBuffer() { void clearBuffer() {
mNewSurface = true; mNewSurface = true;
} }
public static void enableVertexArrays(int va1, int va2) {
if (va1 > 1 || va2 > 1)
Log.d(TAG, "FIXME: enableVertexArrays...");
if ((va1 == 0 || va2 == 0)) {
if (!vertexArray[0]) {
GLES20.glEnableVertexAttribArray(0);
vertexArray[0] = true;
}
} else {
if (vertexArray[0]) {
GLES20.glDisableVertexAttribArray(0);
vertexArray[0] = false;
}
}
if ((va1 == 1 || va2 == 1)) {
if (!vertexArray[1]) {
GLES20.glEnableVertexAttribArray(1);
vertexArray[1] = true;
}
} else {
if (vertexArray[1]) {
GLES20.glDisableVertexAttribArray(1);
vertexArray[1] = false;
}
}
}
} }

View File

@ -37,12 +37,12 @@ public final class MapTile extends JobTile {
/** /**
* tile has new data to upload to gl * tile has new data to upload to gl
*/ */
boolean newData; //boolean newData;
/** /**
* tile is loaded and ready for drawing. * tile is loaded and ready for drawing.
*/ */
boolean isReady; //boolean isReady;
/** /**
* tile is in view region. * tile is in view region.
@ -80,7 +80,7 @@ public final class MapTile extends JobTile {
} }
boolean isActive() { boolean isActive() {
return isLoading || newData || isReady; return state != 0;
} }
boolean isLocked() { boolean isLocked() {
@ -91,18 +91,22 @@ public final class MapTile extends JobTile {
locked++; locked++;
if (locked > 1 || isReady || newData) if (locked > 1)
return; return;
//if (isReady || newData)
// return;
MapTile p = rel.parent.tile; MapTile p = rel.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) { if (p != null && (p.state != 0)) {
proxies |= PROXY_PARENT; proxies |= PROXY_PARENT;
p.refs++; p.refs++;
} }
// FIXME handle root-tile case?
p = rel.parent.parent.tile; p = rel.parent.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) { if (p != null && (p.state != 0)) {
proxies |= PROXY_GRAMPA; proxies |= PROXY_GRAMPA;
p.refs++; p.refs++;
} }
@ -110,7 +114,7 @@ public final class MapTile extends JobTile {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
if (rel.child[j] != null) { if (rel.child[j] != null) {
p = rel.child[j].tile; p = rel.child[j].tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) { if (p != null && (p.state != 0)) {
proxies |= (1 << j); proxies |= (1 << j);
p.refs++; p.refs++;
} }

View File

@ -14,6 +14,8 @@
*/ */
package org.oscim.renderer; package org.oscim.renderer;
import static org.oscim.generator.JobTile.STATE_NONE;
import org.oscim.core.MercatorProjection; import org.oscim.core.MercatorProjection;
import org.oscim.core.Tag; import org.oscim.core.Tag;
import org.oscim.core.Tile; import org.oscim.core.Tile;
@ -38,7 +40,6 @@ import org.oscim.view.MapView;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.FloatMath;
import android.util.Log; import android.util.Log;
/** /**
@ -395,13 +396,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
mDebugDrawPolygons = !debugSettings.mDisablePolygons; mDebugDrawPolygons = !debugSettings.mDisablePolygons;
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted; mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
if (tile.newData || tile.isReady || tile.layers != null) { if (tile.layers != null) {
// should be fixed now. // should be fixed now.
Log.d(TAG, "XXX tile already loaded " Log.d(TAG, "XXX tile already loaded "
+ tile + " " + tile + " " + tile.state);
+ tile.newData + " "
+ tile.isReady + " "
+ tile.isLoading);
return false; return false;
} }
@ -415,8 +413,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// acount for area changes with latitude // acount for area changes with latitude
mProjectionScaleFactor = 0.5f + 0.5f * ( mProjectionScaleFactor = 0.5f + 0.5f * (
FloatMath.sin((float) (Math.abs(MercatorProjection (float) Math.sin(Math.abs(MercatorProjection
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180)))); .pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180)));
mLayers = new Layers(); mLayers = new Layers();
@ -426,7 +424,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
mLayers = null; mLayers = null;
mLabels = null; mLabels = null;
mCurLineLayer = null; mCurLineLayer = null;
tile.isLoading = false;
// FIXME add STATE_FAILED?
tile.state = STATE_NONE;
return false; return false;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 Hannes Janetzek * Copyright 2012 OpenScienceMap
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -12,8 +12,14 @@
* You should have received a copy of the GNU Lesser General Public License along with * You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.oscim.renderer; 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.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -25,9 +31,11 @@ import org.oscim.renderer.layer.VertexPool;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition; import org.oscim.view.MapViewPosition;
import android.util.FloatMath;
import android.util.Log; import android.util.Log;
/**
* @author Hannes Janetzek
*/
public class TileManager { public class TileManager {
static final String TAG = TileManager.class.getSimpleName(); static final String TAG = TileManager.class.getSimpleName();
@ -266,11 +274,7 @@ public class TileManager {
td = new TileSet(newTiles.length); td = new TileSet(newTiles.length);
mTileSets.add(td); mTileSets.add(td);
} }
// else if (td.serial > mUpdateCnt) {
// Log.d(TAG, "ignore previous tile data " + td.cnt);
// // tile data was cleared, ignore tiles
// td.cnt = 0;
// }
nextTiles = td.tiles; nextTiles = td.tiles;
// unlock previously active tiles // unlock previously active tiles
@ -442,9 +446,7 @@ public class TileManager {
private static void clearTile(MapTile t) { private static void clearTile(MapTile t) {
t.newData = false; t.state = STATE_NONE;
t.isLoading = false;
t.isReady = false;
if (t.layers != null) { if (t.layers != null) {
t.layers.clear(); t.layers.clear();
@ -486,7 +488,7 @@ public class TileManager {
dx %= center; dx %= center;
dy %= center; dy %= center;
//t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f; //t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f;
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f; t.distance = (float) Math.sqrt((dx * dx + dy * dy)) * 0.25f;
} else if (diff > 0) { } else if (diff > 0) {
// tile zoom level is child of current // tile zoom level is child of current
@ -501,7 +503,7 @@ public class TileManager {
dx %= center; dx %= center;
dy %= center; dy %= center;
//t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)); //t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
t.distance = FloatMath.sqrt((dx * dx + dy * dy)); t.distance = (float) Math.sqrt((dx * dx + dy * dy));
} else { } else {
// tile zoom level is parent of current // tile zoom level is parent of current
@ -510,7 +512,7 @@ public class TileManager {
dx %= center; dx %= center;
dy %= center; dy %= center;
//t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f); //t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f);
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f); t.distance = (float) Math.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
} }
} }
} }
@ -545,7 +547,7 @@ public class TileManager {
// dont remove tile used by GLRenderer, or somewhere else // dont remove tile used by GLRenderer, or somewhere else
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.isLoading) { } else if (t.state == STATE_LOADING) {
// NOTE: if we add tile back and set loading=false, on next // NOTE: if we add tile back and set loading=false, on next
// limitCache the tile will be removed. clearTile could // limitCache the tile will be removed. clearTile could
// interfere with TileGenerator. so clear in passTile() // interfere with TileGenerator. so clear in passTile()
@ -573,8 +575,8 @@ public class TileManager {
// remove tiles already uploaded to vbo // remove tiles already uploaded to vbo
for (int i = 0; i < size;) { for (int i = 0; i < size;) {
MapTile t = mTilesLoaded.get(i); MapTile t = mTilesLoaded.get(i);
// t.rel == null means tile was removed in limitCache // t.rel == null means tile was removed in limitCache -- but then newdata is false anyway?
if (!t.newData || t.rel == null) { if (t.state == STATE_READY || t.state == STATE_NONE) {// || t.rel == null) {
mTilesLoaded.remove(i); mTilesLoaded.remove(i);
size--; size--;
continue; continue;
@ -614,7 +616,7 @@ public class TileManager {
public synchronized boolean passTile(JobTile jobTile) { public synchronized boolean passTile(JobTile jobTile) {
MapTile tile = (MapTile) jobTile; MapTile tile = (MapTile) jobTile;
if (!tile.isLoading) { if (tile.state != STATE_LOADING) {
// no one should be able to use this tile now, TileGenerator passed // no one should be able to use this tile now, TileGenerator passed
// it, GL-Thread does nothing until newdata is set. // it, GL-Thread does nothing until newdata is set.
//Log.d(TAG, "passTile: failed loading " + tile); //Log.d(TAG, "passTile: failed loading " + tile);
@ -631,12 +633,15 @@ public class TileManager {
if (tile.vbo == null) { if (tile.vbo == null) {
Log.d(TAG, "no VBOs left for " + tile); Log.d(TAG, "no VBOs left for " + tile);
tile.isLoading = false; //tile.isLoading = false;
clearTile(tile);
return true; return true;
} }
tile.newData = true; tile.state = STATE_NEW_DATA;
tile.isLoading = false;
//tile.newData = true;
//tile.isLoading = false;
mMapView.render(); mMapView.render();