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

View File

@ -16,10 +16,13 @@ package org.oscim.generator;
import org.oscim.core.Tile;
import android.util.Log;
/**
*
*/
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 NEWDATA = 1 << 1;
// 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 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
*/
public boolean isLoading;
//public boolean isLoading;
public byte state;
/**
* 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_MINUS_SRC_ALPHA;
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.ByteOrder;
@ -166,6 +168,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
holder = new MapTile(x, y, mZoom);
holder.isVisible = true;
holder.holder = tile;
tile.isVisible = true;
tiles[cnt + mHolderCount++] = holder;
}
}
@ -281,20 +284,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return true;
}
private static boolean uploadTileData(MapTile tile) {
if (tile.layers != null) {
tile.isReady = uploadLayers(tile.layers, tile.vbo, true);
if (!tile.isReady) {
Log.d(TAG, "uploadTileData " + tile + " is empty!");
private static void uploadTileData(MapTile tile) {
if (tile.layers == null) {
BufferObject.release(tile.vbo);
tile.vbo = null;
} else if (!uploadLayers(tile.layers, tile.vbo, true)) {
Log.d(TAG, "uploadTileData " + tile + " failed!");
tile.layers.clear();
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) {
@ -307,10 +309,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
return renderOverlay.isReady;
}
private static void checkBufferUsage() {
private static void checkBufferUsage(boolean force) {
// try to clear some unused vbo when exceding limit
if (mBufferMemoryUsage < LIMIT_BUFFERS) {
if (!force && mBufferMemoryUsage < LIMIT_BUFFERS) {
if (CACHE_TILES < CACHE_TILES_MAX)
CACHE_TILES += 50;
return;
@ -457,23 +459,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!tile.isVisible)
continue;
if (tile.newData) {
if (tile.state == STATE_NEW_DATA) {
uploadTileData(tile);
continue;
}
if (tile.holder != null) {
// load tile that is referenced by this holder
if (tile.holder.newData)
if (tile.holder.state == STATE_NEW_DATA)
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
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
MapTile rel = tile.rel.parent.tile;
if (rel.newData)
if (rel.state == STATE_NEW_DATA)
uploadTileData(rel);
continue;
@ -483,14 +485,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
continue;
MapTile rel = tile.rel.child[c].tile;
if (rel != null && rel.newData)
if (rel != null && rel.state == STATE_NEW_DATA)
uploadTileData(rel);
}
}
}
if (uploadCnt > 0)
checkBufferUsage();
checkBufferUsage(false);
tilesChanged |= (uploadCnt > 0);
@ -507,7 +509,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
for (int i = 0; i < tileCnt; i++) {
MapTile t = tiles[i];
if (t.isVisible && t.isReady)
if (t.isVisible && t.state == STATE_READY)
drawTile(t);
}
@ -517,7 +519,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// TODO draw proxies for placeholder...
for (int i = 0; i < tileCnt; 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);
}
@ -577,6 +579,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mapPosition.viewMatrix, 0);
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.
@ -598,6 +605,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (tile.holder != null)
tile = tile.holder;
if (tile.layers == null)
return;
GLES20.glPolygonOffset(0, mDrawCount++);
// 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;
if (c.isReady) {
if (c.state == STATE_READY) {
drawTile(c);
drawn++;
}
@ -669,7 +679,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!drawProxyChild(tile)) {
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
MapTile t = tile.rel.parent.tile;
if (t.isReady) {
if (t.state == STATE_READY) {
drawTile(t);
drawn = true;
}
@ -677,7 +687,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
MapTile t = tile.rel.parent.parent.tile;
if (t.isReady)
if (t.state == STATE_READY)
drawTile(t);
}
@ -686,14 +696,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// prefer drawing parent
MapTile t = tile.rel.parent.tile;
if (t != null && t.isReady) {
if (t != null && t.state == STATE_READY) {
drawTile(t);
} else if (!drawProxyChild(tile)) {
if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
t = tile.rel.parent.parent.tile;
if (t.isReady)
if (t.state == STATE_READY)
drawTile(t);
}
}
@ -789,4 +799,33 @@ public class GLRenderer implements GLSurfaceView.Renderer {
void clearBuffer() {
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
*/
boolean newData;
//boolean newData;
/**
* tile is loaded and ready for drawing.
*/
boolean isReady;
//boolean isReady;
/**
* tile is in view region.
@ -80,7 +80,7 @@ public final class MapTile extends JobTile {
}
boolean isActive() {
return isLoading || newData || isReady;
return state != 0;
}
boolean isLocked() {
@ -91,18 +91,22 @@ public final class MapTile extends JobTile {
locked++;
if (locked > 1 || isReady || newData)
if (locked > 1)
return;
//if (isReady || newData)
// return;
MapTile p = rel.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) {
if (p != null && (p.state != 0)) {
proxies |= PROXY_PARENT;
p.refs++;
}
// FIXME handle root-tile case?
p = rel.parent.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) {
if (p != null && (p.state != 0)) {
proxies |= PROXY_GRAMPA;
p.refs++;
}
@ -110,7 +114,7 @@ public final class MapTile extends JobTile {
for (int j = 0; j < 4; j++) {
if (rel.child[j] != null) {
p = rel.child[j].tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) {
if (p != null && (p.state != 0)) {
proxies |= (1 << j);
p.refs++;
}

View File

@ -14,6 +14,8 @@
*/
package org.oscim.renderer;
import static org.oscim.generator.JobTile.STATE_NONE;
import org.oscim.core.MercatorProjection;
import org.oscim.core.Tag;
import org.oscim.core.Tile;
@ -38,7 +40,6 @@ import org.oscim.view.MapView;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.util.FloatMath;
import android.util.Log;
/**
@ -395,13 +396,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
mDebugDrawPolygons = !debugSettings.mDisablePolygons;
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
if (tile.newData || tile.isReady || tile.layers != null) {
if (tile.layers != null) {
// should be fixed now.
Log.d(TAG, "XXX tile already loaded "
+ tile + " "
+ tile.newData + " "
+ tile.isReady + " "
+ tile.isLoading);
+ tile + " " + tile.state);
return false;
}
@ -415,8 +413,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// acount for area changes with latitude
mProjectionScaleFactor = 0.5f + 0.5f * (
FloatMath.sin((float) (Math.abs(MercatorProjection
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180))));
(float) Math.sin(Math.abs(MercatorProjection
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)) * (Math.PI / 180)));
mLayers = new Layers();
@ -426,7 +424,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
mLayers = null;
mLabels = null;
mCurLineLayer = null;
tile.isLoading = false;
// FIXME add STATE_FAILED?
tile.state = STATE_NONE;
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
* 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
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
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.Collections;
@ -25,9 +31,11 @@ import org.oscim.renderer.layer.VertexPool;
import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
import android.util.FloatMath;
import android.util.Log;
/**
* @author Hannes Janetzek
*/
public class TileManager {
static final String TAG = TileManager.class.getSimpleName();
@ -266,11 +274,7 @@ public class TileManager {
td = new TileSet(newTiles.length);
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;
// unlock previously active tiles
@ -442,9 +446,7 @@ public class TileManager {
private static void clearTile(MapTile t) {
t.newData = false;
t.isLoading = false;
t.isReady = false;
t.state = STATE_NONE;
if (t.layers != null) {
t.layers.clear();
@ -486,7 +488,7 @@ public class TileManager {
dx %= center;
dy %= center;
//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) {
// tile zoom level is child of current
@ -501,7 +503,7 @@ public class TileManager {
dx %= center;
dy %= center;
//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 {
// tile zoom level is parent of current
@ -510,7 +512,7 @@ public class TileManager {
dx %= center;
dy %= center;
//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
Log.d(TAG, "limitCache: tile still locked " + t + " " + t.distance);
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
// limitCache the tile will be removed. clearTile could
// interfere with TileGenerator. so clear in passTile()
@ -573,8 +575,8 @@ public class TileManager {
// remove tiles already uploaded to vbo
for (int i = 0; i < size;) {
MapTile t = mTilesLoaded.get(i);
// t.rel == null means tile was removed in limitCache
if (!t.newData || t.rel == null) {
// t.rel == null means tile was removed in limitCache -- but then newdata is false anyway?
if (t.state == STATE_READY || t.state == STATE_NONE) {// || t.rel == null) {
mTilesLoaded.remove(i);
size--;
continue;
@ -614,7 +616,7 @@ public class TileManager {
public synchronized boolean passTile(JobTile 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
// it, GL-Thread does nothing until newdata is set.
//Log.d(TAG, "passTile: failed loading " + tile);
@ -631,12 +633,15 @@ public class TileManager {
if (tile.vbo == null) {
Log.d(TAG, "no VBOs left for " + tile);
tile.isLoading = false;
//tile.isLoading = false;
clearTile(tile);
return true;
}
tile.newData = true;
tile.isLoading = false;
tile.state = STATE_NEW_DATA;
//tile.newData = true;
//tile.isLoading = false;
mMapView.render();