use BufferObject.loadBufferData

This commit is contained in:
Hannes Janetzek 2013-05-11 22:50:20 +02:00
parent 8ac661d727
commit b463ca7e3b
5 changed files with 77 additions and 93 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);