diff --git a/src/org/oscim/layers/tile/TileRenderLayer.java b/src/org/oscim/layers/tile/TileRenderLayer.java index 6e2d4acf..ff10e6b5 100644 --- a/src/org/oscim/layers/tile/TileRenderLayer.java +++ b/src/org/oscim/layers/tile/TileRenderLayer.java @@ -31,10 +31,12 @@ public class TileRenderLayer extends RenderLayer { private final static String TAG = TileRenderLayer.class.getName(); private final TileManager mTileManager; + private int mUploadSerial; public TileRenderLayer(MapView mapView, TileManager tileManager) { super(mapView); mTileManager = tileManager; + mUploadSerial = 0; } boolean mFaded; @@ -66,7 +68,10 @@ public class TileRenderLayer extends RenderLayer { tileCnt += mNumTileHolder; /* prepare tile for rendering */ - compileTileLayers(tiles, tileCnt); + if (compileTileLayers(tiles, tileCnt) > 0){ + mUploadSerial++; + BufferObject.checkBufferUsage(false); + } TileRenderer.draw(tiles, tileCnt, pos, m, mFaded); } @@ -103,14 +108,14 @@ public class TileRenderLayer extends RenderLayer { continue; if (tile.state == STATE_NEW_DATA) { - uploadTileData(tile); + uploadCnt += uploadTileData(tile); continue; } if (tile.holder != null) { // load tile that is referenced by this holder if (tile.holder.state == STATE_NEW_DATA) - uploadTileData(tile.holder); + uploadCnt += uploadTileData(tile.holder); tile.state = tile.holder.state; continue; @@ -120,7 +125,7 @@ public class TileRenderLayer extends RenderLayer { if ((tile.proxies & MapTile.PROXY_PARENT) != 0) { MapTile rel = tile.rel.parent.item; if (rel.state == STATE_NEW_DATA) - uploadTileData(rel); + uploadCnt += uploadTileData(rel); // dont load child proxies continue; @@ -132,21 +137,17 @@ public class TileRenderLayer extends RenderLayer { MapTile rel = tile.rel.get(i); if (rel != null && rel.state == STATE_NEW_DATA) - uploadTileData(rel); + uploadCnt += uploadTileData(rel); } } - - if (uploadCnt > 0) - GLRenderer.checkBufferUsage(false); - return uploadCnt; } - private static void uploadTileData(MapTile tile) { + private static int uploadTileData(MapTile tile) { tile.state = STATE_READY; if (tile.layers == null) - return; + return 0; int newSize = tile.layers.getSize(); if (newSize > 0) { @@ -161,8 +162,10 @@ public class TileRenderLayer extends RenderLayer { tile.layers.vbo = null; tile.layers.clear(); tile.layers = null; + return 0; } } + return 1; } private final Object tilelock = new Object(); @@ -202,8 +205,10 @@ public class TileRenderLayer extends RenderLayer { } // same tiles as before - if (tileSet.serial == mDrawTiles.serial) - return false; + //if (tileSet.serial == mDrawTiles.serial) + //return false; + + int prevSerial = tileSet.serial; // ensure tiles keep visible state synchronized (tilelock) { @@ -229,8 +234,10 @@ public class TileRenderLayer extends RenderLayer { tileSet.tiles[tileSet.cnt++] = t; } } + tileSet.serial = mUploadSerial; } - return true; + + return prevSerial != tileSet.serial; } public void releaseTiles(TileSet td) { diff --git a/src/org/oscim/renderer/BufferObject.java b/src/org/oscim/renderer/BufferObject.java index 8b920dec..3c8a5c12 100644 --- a/src/org/oscim/renderer/BufferObject.java +++ b/src/org/oscim/renderer/BufferObject.java @@ -15,7 +15,7 @@ package org.oscim.renderer; -import java.nio.ByteBuffer; +import java.nio.ShortBuffer; import android.opengl.GLES20; import android.util.Log; @@ -23,6 +23,11 @@ import android.util.Log; public final class BufferObject { private final static String TAG = BufferObject.class.getName(); + private static final int MB = 1024 * 1024; + private static final int LIMIT_BUFFERS = 16 * MB; + + + // ------------------------------------------------------------- // GL id public int id; @@ -35,16 +40,25 @@ public final class BufferObject { this.id = id; } - public void uploadArrayBuffer(ByteBuffer buf, int newSize, int type){ + int bufferType; + + public void loadBufferData(ShortBuffer buf, int newSize, int type){ + boolean clear = false; + + if (type != bufferType){ + if (bufferType != 0) + clear = true; + bufferType = 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){ + if (!clear && (size > newSize) && (size < newSize * 4)){ GLES20.glBufferSubData(type, 0, newSize, buf); } else { - //mBufferMemoryUsage += newSize - layers.vbo.size; + mBufferMemoryUsage += newSize - size; size = newSize; @@ -61,6 +75,21 @@ public final class BufferObject { } // ---------------------------- pool ---------------------------- + // bytes currently loaded in VBOs + private static int mBufferMemoryUsage; + + public static void checkBufferUsage(boolean force) { + // try to clear some unused vbo when exceding limit + if (mBufferMemoryUsage < LIMIT_BUFFERS) + return; + + Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB"); + + mBufferMemoryUsage -= BufferObject.limitUsage(1024*1024); + + Log.d(TAG, "now: " + mBufferMemoryUsage / MB + "MB"); + } + 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 e8fb5585..2ca24fd3 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -15,7 +15,6 @@ package org.oscim.renderer; import static android.opengl.GLES20.GL_ARRAY_BUFFER; -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; @@ -53,7 +52,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { private static final int MB = 1024 * 1024; private static final int SHORT_BYTES = 2; private static final int CACHE_TILES_MAX = 250; - private static final int LIMIT_BUFFERS = 16 * MB; + public static final float COORD_SCALE = 8.0f; @@ -71,9 +70,6 @@ public class GLRenderer implements GLSurfaceView.Renderer { private static short[] mFillCoords; - // bytes currently loaded in VBOs - private static int mBufferMemoryUsage; - public class Matrices { // do not modify any of these public final Matrix4 viewproj = new Matrix4(); @@ -98,11 +94,8 @@ public class GLRenderer implements GLSurfaceView.Renderer { (-screenWidth / 2) * ratio * scale, (-screenHeight / 2) * ratio * scale, ratio); - // - // mvp.setTransScale(-screenWidth / ratio, - // screenHeight / ratio, ratio); - mvp.multiplyMM(proj, mvp); + mvp.multiplyLhs(proj); } } @@ -213,41 +206,10 @@ 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 - && mBufferMemoryUsage < LIMIT_BUFFERS) { - GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf); - } else { - mBufferMemoryUsage += newSize - layers.vbo.size; - layers.vbo.size = newSize; - GLES20.glBufferData(GL_ARRAY_BUFFER, layers.vbo.size, sbuf, GL_DYNAMIC_DRAW); - } - + layers.vbo.loadBufferData(sbuf, newSize, GL_ARRAY_BUFFER); return true; } - public static void checkBufferUsage(boolean force) { - // try to clear some unused vbo when exceding limit - - if (!force && mBufferMemoryUsage < LIMIT_BUFFERS) { - if (CACHE_TILES < CACHE_TILES_MAX) - CACHE_TILES += 50; - return; - } - - Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB"); - - mBufferMemoryUsage -= BufferObject.limitUsage(2 * MB); - - Log.d(TAG, "now: " + mBufferMemoryUsage / MB + "MB"); - - if (mBufferMemoryUsage > LIMIT_BUFFERS && CACHE_TILES > 100) - CACHE_TILES -= 50; - } - private long lastDraw = 0; @Override @@ -303,11 +265,11 @@ public class GLRenderer implements GLSurfaceView.Renderer { if (changed) mMapViewPosition.getMapViewProjection(mMatrices.mapPlane); - mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj); + mMapViewPosition.getMatrix(mMatrices.view, mMatrices.proj, mMatrices.viewproj); if (debugView) { mMatrices.mvp.setScale(0.5f, 0.5f, 1); - mMatrices.viewproj.multiplyMM(mMatrices.mvp, mMatrices.viewproj); + mMatrices.viewproj.multiplyLhs(mMatrices.mvp); } } @@ -336,7 +298,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { } if (GlUtils.checkGlOutOfMemory("finish")) { - checkBufferUsage(true); + BufferObject.checkBufferUsage(true); // TODO also throw out some textures etc } } @@ -361,7 +323,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { // modify this to scale only the view, to see better which tiles // are rendered mMatrices.mvp.setScale(0.5f, 0.5f, 1); - mMatrices.proj.multiplyMM(mMatrices.mvp, mMatrices.proj); + mMatrices.proj.multiplyLhs(mMatrices.mvp); } GLES20.glViewport(0, 0, width, height); @@ -373,10 +335,13 @@ public class GLRenderer implements GLSurfaceView.Renderer { GLES20.glDisable(GLES20.GL_CULL_FACE); GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + //mBufferMemoryUsage = 0; + if (!mNewSurface) { mMapView.redrawMap(false); return; } + mNewSurface = false; // set initial temp buffer size @@ -407,16 +372,6 @@ public class GLRenderer implements GLSurfaceView.Renderer { indices.length * 2, shortBuffer, GLES20.GL_STATIC_DRAW); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - mBufferMemoryUsage = 0; - //mDrawTiles = null; - - int numTiles = (screenWidth / (Tile.SIZE / 2) + 2) - * (screenHeight / (Tile.SIZE / 2) + 2); - - // Set up vertex buffer objects - int numVBO = (CACHE_TILES + (numTiles * 2)); - BufferObject.init(numVBO); - if (mClearColor != null) mUpdateColor = true; @@ -432,6 +387,9 @@ public class GLRenderer implements GLSurfaceView.Renderer { // classes that require GL context for initialization Layers.initRenderer(); + // Set up some vertex buffer objects + BufferObject.init(CACHE_TILES); + mNewSurface = true; } diff --git a/src/org/oscim/renderer/layers/BasicRenderLayer.java b/src/org/oscim/renderer/layers/BasicRenderLayer.java index bf19eb0e..d4fc940f 100644 --- a/src/org/oscim/renderer/layers/BasicRenderLayer.java +++ b/src/org/oscim/renderer/layers/BasicRenderLayer.java @@ -99,7 +99,7 @@ public abstract class BasicRenderLayer extends RenderLayer { @Override public void compile() { int newSize = layers.getSize(); - if (newSize == 0) { + if (newSize <= 0) { BufferObject.release(layers.vbo); layers.vbo = null; isReady = false; @@ -107,15 +107,13 @@ public abstract class BasicRenderLayer extends RenderLayer { } if (layers.vbo == null) { - layers.vbo = BufferObject.get(0); + layers.vbo = BufferObject.get(newSize); if (layers.vbo == null) return; } - if (newSize > 0) { - if (GLRenderer.uploadLayers(layers, newSize, true)) - isReady = true; - } + if (GLRenderer.uploadLayers(layers, newSize, true)) + isReady = true; } } diff --git a/src/org/oscim/renderer/sublayers/ExtrusionLayer.java b/src/org/oscim/renderer/sublayers/ExtrusionLayer.java index 0f28e034..d90bdd55 100644 --- a/src/org/oscim/renderer/sublayers/ExtrusionLayer.java +++ b/src/org/oscim/renderer/sublayers/ExtrusionLayer.java @@ -387,12 +387,6 @@ public class ExtrusionLayer extends Layer { if (mNumVertices == 0 || compiled) return; - vboVertices = BufferObject.get(0); - vboIndices = BufferObject.get(0); - - // upload indices - //sbuf.clear(); - mNumIndices = 0; for (int i = 0; i < 4; i++) { for (VertexItem vi = mIndices[i]; vi != null; vi = vi.next) { @@ -403,10 +397,9 @@ public class ExtrusionLayer extends Layer { } sbuf.flip(); - vboIndices.size = mNumIndices * 2; - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, vboIndices.id); - GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, - vboIndices.size, sbuf, GLES20.GL_DYNAMIC_DRAW); + int size = mNumIndices*2; + vboIndices = BufferObject.get(size); + vboIndices.loadBufferData(sbuf,size, GLES20.GL_ELEMENT_ARRAY_BUFFER); // upload vertices sbuf.clear(); @@ -414,10 +407,9 @@ public class ExtrusionLayer extends Layer { sbuf.put(vi.vertices, 0, vi.used); sbuf.flip(); - vboVertices.size = mNumVertices * 4 * 2; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboVertices.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, - vboVertices.size, sbuf, GLES20.GL_DYNAMIC_DRAW); + size = mNumVertices * 4 * 2; + vboVertices = BufferObject.get(size); + vboVertices.loadBufferData(sbuf, size, GLES20.GL_ARRAY_BUFFER); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);