diff --git a/src/org/oscim/renderer/BufferObject.java b/src/org/oscim/renderer/BufferObject.java index 46209a01..9e348041 100644 --- a/src/org/oscim/renderer/BufferObject.java +++ b/src/org/oscim/renderer/BufferObject.java @@ -15,6 +15,8 @@ package org.oscim.renderer; +import java.nio.ByteBuffer; + import android.opengl.GLES20; import android.util.Log; @@ -33,6 +35,23 @@ public final class BufferObject { this.id = id; } + public void uploadArrayBuffer(ByteBuffer buf, int newSize, int type){ + + GLES20.glBindBuffer(type, id); + + // reuse memory allocated for vbo when possible and allocated + // memory is less then four times the new data + if (size > newSize && size < newSize * 4){ + GLES20.glBufferSubData(type, 0, newSize, buf); + } else { + //mBufferMemoryUsage += newSize - layers.vbo.size; + + size = newSize; + + GLES20.glBufferData(type, size, buf, GLES20.GL_DYNAMIC_DRAW); + } + } + // ---------------------------- pool ---------------------------- private static BufferObject pool; static int counter = 0; diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index d0d6e4e9..bb7b4b0c 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -21,6 +21,7 @@ import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.FloatBuffer; import java.nio.ShortBuffer; import java.util.concurrent.locks.ReentrantLock; @@ -65,6 +66,9 @@ public class GLRenderer implements GLSurfaceView.Renderer { private static MapPosition mMapPosition; private static ShortBuffer shortBuffer; + private static FloatBuffer floatBuffer; + private static int tmpBufferSize; + private static short[] mFillCoords; // bytes currently loaded in VBOs @@ -128,27 +132,51 @@ public class GLRenderer implements GLSurfaceView.Renderer { mUpdateColor = true; } + /** + * Only use on GL Thread! + * Get a native ShortBuffer for temporary use. + */ + public static ShortBuffer getShortBuffer(int size) { + if (tmpBufferSize < size * 2) + growBuffer(size * 2); + else + shortBuffer.clear(); + + return shortBuffer; + } + + /** + * Only use on GL Thread! + * Get a native FloatBuffer for temporary use. + */ + public static FloatBuffer getFloatBuffer(int size) { + if (tmpBufferSize < size * 4) + growBuffer(size * 4); + else + floatBuffer.clear(); + + return floatBuffer; + } + + private static void growBuffer(int size) { + Log.d(TAG, "grow buffer " + size); + ByteBuffer buf = ByteBuffer + .allocateDirect(size) + .order(ByteOrder.nativeOrder()); + + floatBuffer = buf.asFloatBuffer(); + shortBuffer = buf.asShortBuffer(); + tmpBufferSize = size; + } + public static boolean uploadLayers(Layers layers, int newSize, boolean addFill) { - GLES20.glBindBuffer(GL_ARRAY_BUFFER, layers.vbo.id); - // add fill coordinates if (addFill) newSize += 8; - ShortBuffer sbuf = shortBuffer; - - if (sbuf.capacity() < newSize) { - shortBuffer = sbuf = ByteBuffer - .allocateDirect(newSize * SHORT_BYTES) - .order(ByteOrder.nativeOrder()) - .asShortBuffer(); - } else { - sbuf.clear(); - // if (addFill) - // sbuf.position(8); - } + ShortBuffer sbuf = getShortBuffer(newSize); if (addFill) sbuf.put(mFillCoords, 0, 8); @@ -166,6 +194,8 @@ public class GLRenderer implements GLSurfaceView.Renderer { } newSize *= SHORT_BYTES; + GLES20.glBindBuffer(GL_ARRAY_BUFFER, layers.vbo.id); + // reuse memory allocated for vbo when possible and allocated // memory is less then four times the new data if (layers.vbo.size > newSize && layers.vbo.size < newSize * 4 @@ -222,8 +252,6 @@ public class GLRenderer implements GLSurfaceView.Renderer { } } - - private static void draw() { long start = 0; @@ -264,7 +292,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { } } - /* update layers*/ + /* update layers */ RenderLayer[] overlays = mMapView.getLayerManager().getRenderLayers(); for (int i = 0, n = overlays.length; i < n; i++) @@ -332,9 +360,8 @@ public class GLRenderer implements GLSurfaceView.Renderer { } mNewSurface = false; - ByteBuffer bbuf = ByteBuffer.allocateDirect(MB >> 2) - .order(ByteOrder.nativeOrder()); - shortBuffer = bbuf.asShortBuffer(); + // set initial temp buffer size + growBuffer(MB >> 2); // upload quad indices used by Texture- and LineTexRenderer int[] vboIds = new int[1]; diff --git a/src/org/oscim/renderer/layer/ExtrusionLayer.java b/src/org/oscim/renderer/layer/ExtrusionLayer.java index 6232dd63..0eb39db1 100644 --- a/src/org/oscim/renderer/layer/ExtrusionLayer.java +++ b/src/org/oscim/renderer/layer/ExtrusionLayer.java @@ -37,9 +37,10 @@ import android.util.Log; public class ExtrusionLayer extends Layer { private final static String TAG = ExtrusionLayer.class.getName(); private static final float S = GLRenderer.COORD_SCALE; - private final VertexItem mVertices; + private VertexItem mVertices; private VertexItem mCurVertices; - private final VertexItem mIndices[], mCurIndices[]; + private VertexItem mIndices[]; + private final VertexItem mCurIndices[]; private LineClipper mClipper; // indices for: @@ -48,10 +49,8 @@ public class ExtrusionLayer extends Layer { public int mNumIndices = 0; public int mNumVertices = 0; - public int mIndicesBufferID; - public int mVertexBufferID; - private BufferObject mIndiceBO; - private BufferObject mVertexBO; + public BufferObject vboIndices; + public BufferObject vboVertices; //private final static int IND_EVEN_SIDE = 0; //private final static int IND_ODD_SIDE = 1; @@ -154,7 +153,7 @@ public class ExtrusionLayer extends Layer { if (simpleOutline && (convex || len <= 8)) addRoofSimple(startVertex, len); - else if (!complexOutline) { + else if (!complexOutline) { complexOutline = true; // keep start postion of polygon and defer roof building // as it modifies the geometry array. @@ -387,13 +386,12 @@ public class ExtrusionLayer extends Layer { if (mNumVertices == 0 || compiled) return; - mVertexBO = BufferObject.get(0); - mIndiceBO = BufferObject.get(0); - mIndicesBufferID = mIndiceBO.id; - mVertexBufferID = mVertexBO.id; + vboVertices = BufferObject.get(0); + vboIndices = BufferObject.get(0); // upload indices - sbuf.clear(); + //sbuf.clear(); + mNumIndices = 0; for (int i = 0; i < 4; i++) { for (VertexItem vi = mIndices[i]; vi != null; vi = vi.next) { @@ -404,10 +402,10 @@ public class ExtrusionLayer extends Layer { } sbuf.flip(); - mIndiceBO.size = mNumIndices * 2; - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); + vboIndices.size = mNumIndices * 2; + GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboIndices.id); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, - mIndiceBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW); + vboIndices.size, sbuf, GLES20.GL_DYNAMIC_DRAW); // upload vertices sbuf.clear(); @@ -415,19 +413,21 @@ 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); + vboVertices.size = mNumVertices * 4 * 2; + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboVertices.id); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, - mVertexBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW); + vboVertices.size, sbuf, GLES20.GL_DYNAMIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - for (VertexItem i : mIndices) - VertexItem.pool.releaseAll(i); + for (int i = 0; i < 4; i++) + VertexItem.pool.releaseAll(mIndices[i]); VertexItem.pool.releaseAll(mVertices); + mIndices = null; + mVertices = null; mClipper = null; compiled = true; @@ -436,15 +436,17 @@ public class ExtrusionLayer extends Layer { @Override protected void clear() { if (compiled) { - BufferObject.release(mIndiceBO); - BufferObject.release(mVertexBO); - mIndiceBO = null; - mVertexBO = null; - //GLES20.glDeleteBuffers(2, mVboIds, 0); + BufferObject.release(vboIndices); + BufferObject.release(vboVertices); + vboIndices = null; + vboVertices = null; } else { + for (int i = 0; i < 4; i++) + VertexItem.pool.releaseAll(mIndices[i]); + mIndices = null; + VertexItem.pool.releaseAll(mVertices); - for (VertexItem i : mIndices) - VertexItem.pool.releaseAll(i); + mVertices = null; } } @@ -501,7 +503,8 @@ public class ExtrusionLayer extends Layer { * @param ioffset offset used to add offset to indices * @return number of triangles in io buffer */ - public static native int triangulate(float[] points, int pos, int len, int numRings, ShortBuffer io, + public static native int triangulate(float[] points, int pos, int len, int numRings, + ShortBuffer io, int ioffset); static { diff --git a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java index d305be12..7c7b6576 100644 --- a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java +++ b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java @@ -14,10 +14,6 @@ */ package org.oscim.renderer.overlays; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; - import org.oscim.core.MapPosition; import org.oscim.core.Tile; import org.oscim.layers.tile.MapTile; @@ -58,9 +54,9 @@ public class ExtrusionOverlay extends RenderLayer { private boolean initialized = false; // FIXME sum up size used while filling layer only up to: - public int mBufferSize = 65536; + //public int mBufferSize = 65536; + private TileSet mTileSet; - private ShortBuffer mShortBuffer; private MapTile[] mTiles; private int mTileCnt; @@ -87,11 +83,6 @@ public class ExtrusionOverlay extends RenderLayer { hVertexPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_pos"); hLightPosition[i] = GLES20.glGetAttribLocation(shaderProgram[i], "a_light"); } - - ByteBuffer buf = ByteBuffer.allocateDirect(mBufferSize) - .order(ByteOrder.nativeOrder()); - - mShortBuffer = buf.asShortBuffer(); } int ready = 0; @@ -121,16 +112,10 @@ public class ExtrusionOverlay extends RenderLayer { continue; if (!el.compiled) { + // FIXME check 'bytes'? int verticesBytes = el.mNumVertices * 8 * 2; - if (verticesBytes > mBufferSize) { - mBufferSize = verticesBytes; - Log.d(TAG, "realloc extrusion buffer " + verticesBytes); - ByteBuffer buf = ByteBuffer.allocateDirect(verticesBytes) - .order(ByteOrder.nativeOrder()); - mShortBuffer = buf.asShortBuffer(); - } - el.compile(mShortBuffer); + el.compile(GLRenderer.getShortBuffer(verticesBytes)); GlUtils.checkGlError("..."); } @@ -205,8 +190,8 @@ public class ExtrusionOverlay extends RenderLayer { setMatrix(pos, m, tiles[i], 0); m.mvp.setAsUniform(uExtMatrix); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); + GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id); + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.vboVertices.id); GLES20.glVertexAttribPointer(uExtVertexPosition, 3, GLES20.GL_SHORT, false, 8, 0); @@ -257,8 +242,8 @@ public class ExtrusionOverlay extends RenderLayer { setMatrix(pos, m, t, d); m.mvp.setAsUniform(uExtMatrix); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); + GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id); + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.vboVertices.id); GLES20.glVertexAttribPointer(uExtVertexPosition, 3, GLES20.GL_SHORT, false, 8, 0); @@ -283,8 +268,8 @@ public class ExtrusionOverlay extends RenderLayer { setMatrix(pos, m, t, d); m.mvp.setAsUniform(uExtMatrix); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); + GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id); + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.vboVertices.id); GLES20.glVertexAttribPointer(uExtVertexPosition, 3, GLES20.GL_SHORT, false, 8, 0);