From a8b25d07ad19a781c7c86de38b2cb96e4d66c333 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek <hannes.janetzek@gmail.com> Date: Sat, 29 Dec 2012 23:34:48 +0100 Subject: [PATCH] keep tile loading state in JobTile.state --- src/org/oscim/generator/JobQueue.java | 7 +- src/org/oscim/generator/JobTile.java | 22 +++++- src/org/oscim/renderer/GLRenderer.java | 95 ++++++++++++++++------- src/org/oscim/renderer/MapTile.java | 18 +++-- src/org/oscim/renderer/TileGenerator.java | 18 ++--- src/org/oscim/renderer/TileManager.java | 45 ++++++----- 6 files changed, 137 insertions(+), 68 deletions(-) diff --git a/src/org/oscim/generator/JobQueue.java b/src/org/oscim/generator/JobQueue.java index 16ac107c..bfdb73e7 100644 --- a/src/org/oscim/generator/JobQueue.java +++ b/src/org/oscim/generator/JobQueue.java @@ -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(); } diff --git a/src/org/oscim/generator/JobTile.java b/src/org/oscim/generator/JobTile.java index 79847d19..a535b727 100644 --- a/src/org/oscim/generator/JobTile.java +++ b/src/org/oscim/generator/JobTile.java @@ -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. diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index 13e7f3b7..c02cba8a 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -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!"); - tile.layers.clear(); - tile.layers = null; - } + 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; + } + } + } } diff --git a/src/org/oscim/renderer/MapTile.java b/src/org/oscim/renderer/MapTile.java index 68f7ee0d..8409c93d 100644 --- a/src/org/oscim/renderer/MapTile.java +++ b/src/org/oscim/renderer/MapTile.java @@ -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++; } diff --git a/src/org/oscim/renderer/TileGenerator.java b/src/org/oscim/renderer/TileGenerator.java index b967220a..f398e805 100644 --- a/src/org/oscim/renderer/TileGenerator.java +++ b/src/org/oscim/renderer/TileGenerator.java @@ -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; } diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java index 7a19f858..1bdab9f0 100644 --- a/src/org/oscim/renderer/TileManager.java +++ b/src/org/oscim/renderer/TileManager.java @@ -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();