diff --git a/src/org/oscim/renderer/BaseMap.java b/src/org/oscim/renderer/BaseMap.java index a4c4c3a7..1c284224 100644 --- a/src/org/oscim/renderer/BaseMap.java +++ b/src/org/oscim/renderer/BaseMap.java @@ -103,7 +103,7 @@ public class BaseMap { if (t.holder != null) t = t.holder; - if (t.layers == null) + if (t.layers == null || t.vbo == null) return; // set Model matrix for tile @@ -149,15 +149,6 @@ public class BaseMap { break; } } - - // if (tile.layers.textureLayers != null) { - // setMatrix(mvp, tile, div, false); - // - // for (Layer l = tile.layers.textureLayers; l != null;) { - // l = TextureRenderer.draw(l, 1, mProjMatrix, mvp, - // tile.layers.texOffset); - // } - // } } private static int drawProxyChild(MapTile tile, MapPosition pos) { diff --git a/src/org/oscim/renderer/BufferObject.java b/src/org/oscim/renderer/BufferObject.java index 079b84a7..27cd22f1 100644 --- a/src/org/oscim/renderer/BufferObject.java +++ b/src/org/oscim/renderer/BufferObject.java @@ -16,17 +16,42 @@ package org.oscim.renderer; import android.opengl.GLES20; +import android.util.Log; public final class BufferObject { + private final static String TAG = BufferObject.class.getName(); + private static BufferObject pool; - static int counter; + static int counter = 0; - static synchronized BufferObject get() { + public static synchronized BufferObject get(int size) { - if (pool == null) - return null; + if (pool == null) { + if (counter != 0) + Log.d(TAG, "missing BufferObjects: " + counter); + + createBuffers(10); + counter += 10; + } counter--; + if (size != 0) { + // sort so that items larger than requested size are promoted in the list + BufferObject prev = null; + for (BufferObject bo = pool; bo != null; bo = bo.next) { + if (bo.size > size) { + if (prev == null) + pool = bo.next; + else + prev.next = bo.next; + + bo.next = null; + Log.d(TAG, "requested: " + size + " got " + bo.size); + return bo; + } + prev = bo; + } + } BufferObject bo = pool; pool = pool.next; bo.next = null; @@ -61,7 +86,11 @@ public final class BufferObject { // return bo; // } - static synchronized void release(BufferObject bo) { + public static synchronized void release(BufferObject bo) { + if (counter > 200) { + Log.d(TAG, "should clear some buffers " + counter); + } + bo.next = pool; pool = bo; counter++; @@ -69,49 +98,56 @@ public final class BufferObject { // Note: only call from GL-Thread static synchronized int limitUsage(int reduce) { + if (pool == null) { + Log.d(TAG, "nothing to free"); + return 0; + } int vboIds[] = new int[10]; - BufferObject[] tmp = new BufferObject[10]; int removed = 0; int freed = 0; + BufferObject prev = pool; - for (BufferObject bo = pool; bo != null; bo = bo.next) { + for (BufferObject bo = pool.next; bo != null;) { if (bo.size > 0) { freed += bo.size; bo.size = 0; - vboIds[removed] = bo.id; - tmp[removed++] = bo; - + vboIds[removed++] = bo.id; + prev.next = bo.next; + bo = bo.next; if (removed == 10 || reduce < freed) break; + + } else { + prev = bo; + bo = bo.next; } } if (removed > 0) { GLES20.glDeleteBuffers(removed, vboIds, 0); - GLES20.glGenBuffers(removed, vboIds, 0); - - for (int i = 0; i < removed; i++) - tmp[i].id = vboIds[i]; + counter -= removed; } return freed; } - static void init(int num) { + static void createBuffers(int num) { int[] mVboIds = new int[num]; GLES20.glGenBuffers(num, mVboIds, 0); - BufferObject bo; - - for (int i = 1; i < num; i++) { - bo = new BufferObject(mVboIds[i]); + for (int i = 0; i < num; i++) { + BufferObject bo = new BufferObject(mVboIds[i]); bo.next = pool; pool = bo; } - counter = num; + } + + static synchronized void init(int num) { + //createBuffers(num); + //counter = num; } public int id; - int size; + public int size; BufferObject next; BufferObject(int id) { diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index 495292e8..b3cc60f0 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -208,13 +208,8 @@ public class GLRenderer implements GLSurfaceView.Renderer { private static int uploadCnt = 0; - private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) { - - int newSize = layers.getSize(); - if (newSize == 0) { - // Log.d(TAG, "empty"); - return true; - } + private static boolean uploadLayers(Layers layers, BufferObject vbo, int newSize, + boolean addFill) { GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id); @@ -278,24 +273,34 @@ public class GLRenderer implements GLSurfaceView.Renderer { 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; - } + } else { + int newSize = tile.layers.getSize(); + if (newSize > 0) { + + 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; + } + } + } tile.state = STATE_READY; } private static boolean uploadOverlayData(RenderOverlay renderOverlay) { + int newSize = renderOverlay.layers.getSize(); + if (newSize > 0) { + if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, newSize, true)) + renderOverlay.isReady = true; - if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, true)) - renderOverlay.isReady = true; - - renderOverlay.newData = false; - + renderOverlay.newData = false; + } return renderOverlay.isReady; } @@ -476,7 +481,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { // helper to compile layers into single vbo if (renderOverlay.newData) { if (renderOverlay.vbo == null) { - renderOverlay.vbo = BufferObject.get(); + renderOverlay.vbo = BufferObject.get(0); if (renderOverlay.vbo == null) continue; diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java index 5c8ed93d..367ffcef 100644 --- a/src/org/oscim/renderer/TileManager.java +++ b/src/org/oscim/renderer/TileManager.java @@ -660,13 +660,13 @@ public class TileManager { return true; } - tile.vbo = BufferObject.get(); - - if (tile.vbo == null) { - Log.d(TAG, "no VBOs left for " + tile); - clearTile(tile); - return true; - } + // tile.vbo = BufferObject.get(false); + // + // if (tile.vbo == null) { + // Log.d(TAG, "no VBOs left for " + tile); + // //clearTile(tile); + // //return true; + // } tile.state = STATE_NEW_DATA; diff --git a/src/org/oscim/renderer/layer/ExtrusionLayer.java b/src/org/oscim/renderer/layer/ExtrusionLayer.java index 78ff4f00..deb36f6c 100644 --- a/src/org/oscim/renderer/layer/ExtrusionLayer.java +++ b/src/org/oscim/renderer/layer/ExtrusionLayer.java @@ -20,6 +20,7 @@ import java.nio.FloatBuffer; import java.nio.ShortBuffer; import org.oscim.core.Tile; +import org.oscim.renderer.BufferObject; import org.oscim.renderer.GLRenderer; import org.oscim.utils.LineClipper; import org.oscim.view.MapView; @@ -31,7 +32,7 @@ import android.util.Log; /** * @author Hannes Janetzek * FIXME check if polygon has self intersections or 0/180 degree - * angles!!! + * angles! */ public class ExtrusionLayer extends Layer { private final static String TAG = ExtrusionLayer.class.getName(); @@ -44,9 +45,12 @@ public class ExtrusionLayer extends Layer { // indices for: // 0. even sides, 1. odd sides, 2. roof, 3. roof outline public int mIndiceCnt[] = { 0, 0, 0, 0 }; + public int mNumIndices = 0; + public int mIndicesBufferID; public int mVertexBufferID; - public int mNumIndices = 0; + private BufferObject mIndiceBO; + private BufferObject mVertexBO; //private final static int IND_EVEN_SIDE = 0; //private final static int IND_ODD_SIDE = 1; @@ -54,7 +58,8 @@ public class ExtrusionLayer extends Layer { private final static int IND_OUTLINE = 3; public boolean compiled = false; - private int[] mVboIds; + + //private int[] mVboIds; public ExtrusionLayer(int level) { this.type = Layer.EXTRUSION; @@ -345,13 +350,18 @@ public class ExtrusionLayer extends Layer { if (mNumVertices == 0 || compiled) return; - mVboIds = new int[2]; - GLES20.glGenBuffers(2, mVboIds, 0); - mIndicesBufferID = mVboIds[0]; - mVertexBufferID = mVboIds[1]; + // mVboIds = new int[2]; + // GLES20.glGenBuffers(2, mVboIds, 0); + // mIndicesBufferID = mVboIds[0]; + // mVertexBufferID = mVboIds[1]; + + // FIXME add in_gl_thread param to make sure we get something here + mVertexBO = BufferObject.get(0); + mIndiceBO = BufferObject.get(0); + mIndicesBufferID = mIndiceBO.id; + mVertexBufferID = mVertexBO.id; // upload indices - sbuf.clear(); mNumIndices = 0; for (int i = 0; i < 4; i++) { @@ -363,9 +373,10 @@ public class ExtrusionLayer extends Layer { } sbuf.flip(); + mIndiceBO.size = mNumIndices * 2; GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, - mNumIndices * 2, sbuf, GLES20.GL_DYNAMIC_DRAW); + mIndiceBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW); // upload vertices sbuf.clear(); @@ -373,9 +384,10 @@ public class ExtrusionLayer extends Layer { sbuf.put(vi.vertices, 0, vi.used); sbuf.flip(); + mVertexBO.size = mNumVertices * 4 * 2; GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, - mNumVertices * 4 * 2, sbuf, GLES20.GL_DYNAMIC_DRAW); + mVertexBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); @@ -393,7 +405,11 @@ public class ExtrusionLayer extends Layer { @Override protected void clear() { if (compiled) { - GLES20.glDeleteBuffers(2, mVboIds, 0); + BufferObject.release(mIndiceBO); + BufferObject.release(mVertexBO); + mIndiceBO = null; + mVertexBO = null; + //GLES20.glDeleteBuffers(2, mVboIds, 0); } else { VertexPool.release(mVertices); for (VertexPoolItem i : mIndices)