need to split pool for ELEMENT_ARRAY and ARRAY_BUFFER

- due to webkit's funky gl implementation one cannot reuse
  a buffer for another type once its target was set..
... anyway api is nicer now :)
This commit is contained in:
Hannes Janetzek 2013-06-28 04:20:25 +02:00
parent 8845a053fb
commit 50cb603bbf
11 changed files with 136 additions and 218 deletions

View File

@ -698,7 +698,7 @@ class TextRenderLayer extends BasicRenderLayer {
@Override
public synchronized void render(MapPosition pos, Matrices m) {
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, layers.vbo.id);
layers.vbo.bind();
GLState.test(false, false);
float scale = (float) (mMapPosition.scale / pos.scale);

View File

@ -17,8 +17,7 @@ package org.oscim.layers.tile;
import static org.oscim.layers.tile.MapTile.STATE_NEW_DATA;
import static org.oscim.layers.tile.MapTile.STATE_READY;
import java.util.Arrays;
import org.oscim.backend.GL20;
import org.oscim.backend.Log;
import org.oscim.core.MapPosition;
import org.oscim.renderer.BufferObject;
@ -65,8 +64,6 @@ public class TileRenderLayer extends RenderLayer {
if (tilesChanged || positionChanged){
updateTileVisibility(m.mapPlane);
Log.d(TAG, tileCnt + " >> " + Arrays.deepToString(tiles));
}
tileCnt += mNumTileHolder;
@ -156,7 +153,7 @@ public class TileRenderLayer extends RenderLayer {
if (newSize > 0) {
if (tile.layers.vbo == null)
tile.layers.vbo = BufferObject.get(newSize);
tile.layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize);
if (!GLRenderer.uploadLayers(tile.layers, newSize, true)) {
Log.d(TAG, "BUG uploadTileData " + tile + " failed!");

View File

@ -130,7 +130,7 @@ public class TileRenderer {
return;
}
t.layers.vbo.bindArrayBuffer();
t.layers.vbo.bind();
// place tile relative to map position
int z = tile.zoomLevel;

View File

@ -37,44 +37,35 @@ public final class BufferObject {
BufferObject next;
BufferObject(int id) {
int target;
BufferObject(int target, int id) {
this.id = id;
this.target = target;
}
int bufferType;
public void loadBufferData(Buffer buf, int newSize, int type) {
public void loadBufferData(Buffer buf, int newSize) {
boolean clear = false;
if (type != bufferType) {
if (bufferType != 0)
clear = true;
bufferType = type;
}
if (buf.position() != 0){
if (buf.position() != 0) {
Log.d(TAG, "rewind your buffer: " + buf.position());
}
GL.glBindBuffer(type, id);
GL.glBindBuffer(target, id);
// reuse memory allocated for vbo when possible and allocated
// memory is less then four times the new data
if (!clear && (size > newSize) && (size < newSize * 4)) {
GL.glBufferSubData(type, 0, newSize, buf);
GL.glBufferSubData(target, 0, newSize, buf);
} else {
mBufferMemoryUsage += newSize - size;
size = newSize;
GL.glBufferData(type, size, buf, GL20.GL_DYNAMIC_DRAW);
GL.glBufferData(target, size, buf, GL20.GL_DYNAMIC_DRAW);
}
}
public void bindArrayBuffer() {
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, id);
}
public void bindIndexBuffer() {
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, id);
public void bind() {
GL.glBindBuffer(target, id);
}
// ---------------------------- pool ----------------------------
@ -87,37 +78,39 @@ public final class BufferObject {
return;
Log.d(TAG, "buffer object usage: "
+ mBufferMemoryUsage / MB
+ "MB, force: " + force);
+ mBufferMemoryUsage / MB
+ "MB, force: " + force);
mBufferMemoryUsage -= BufferObject.limitUsage(1024 * 1024);
Log.d(TAG, "now: " + mBufferMemoryUsage / MB + "MB");
}
private static BufferObject pool;
static int counter = 0;
private static BufferObject pool[] = new BufferObject[2];
static int counter[] = new int[2];
public static synchronized BufferObject get(int size) {
public static synchronized BufferObject get(int target, int size) {
if (pool == null) {
if (counter != 0)
int t = (target == GL20.GL_ARRAY_BUFFER) ? 0 : 1;
if (pool[t] == null) {
if (counter[t] != 0)
Log.d(TAG, "BUG: missing BufferObjects: " + counter);
createBuffers(10);
counter += 10;
createBuffers(target, 10);
counter[t] += 10;
}
counter--;
counter[t]--;
if (size != 0) {
// find an item that has bound more than 'size' bytes.
// this has the advantage that either memory can be reused or
// a large unused block will be replaced by a smaller one.
BufferObject prev = null;
for (BufferObject bo = pool; bo != null; bo = bo.next) {
for (BufferObject bo = pool[t]; bo != null; bo = bo.next) {
if (bo.size > size) {
if (prev == null)
pool = bo.next;
pool[t] = bo.next;
else
prev.next = bo.next;
@ -127,8 +120,9 @@ public final class BufferObject {
prev = bo;
}
}
BufferObject bo = pool;
pool = pool.next;
BufferObject bo = pool[t];
pool[t] = pool[t].next;
bo.next = null;
return bo;
}
@ -137,64 +131,78 @@ public final class BufferObject {
if (bo == null)
return;
//if (counter > 200) {
// Log.d(TAG, "should clear some buffers " + counter);
//}
// if (counter > 200) {
// Log.d(TAG, "should clear some buffers " + counter);
// }
int t = (bo.target == GL20.GL_ARRAY_BUFFER) ? 0 : 1;
bo.next = pool;
pool = bo;
counter++;
bo.next = pool[t];
pool[t] = bo;
counter[t]++;
}
// 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];
int removed = 0;
int freed = 0;
BufferObject prev = pool;
for (BufferObject bo = pool.next; bo != null;) {
if (bo.size > 0) {
freed += bo.size;
bo.size = 0;
vboIds[removed++] = bo.id;
prev.next = bo.next;
bo = bo.next;
if (removed == 10 || reduce < freed)
break;
for (int t = 0; t < 2; t++) {
} else {
prev = bo;
bo = bo.next;
int removed = 0;
BufferObject prev = pool[t];
if (prev == null) {
Log.d(TAG, "nothing to free");
return 0;
}
for (BufferObject bo = pool[t].next; bo != null;) {
if (bo.size > 0) {
freed += bo.size;
bo.size = 0;
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) {
GlUtils.glDeleteBuffers(removed, vboIds);
counter[t] -= removed;
}
}
if (removed > 0) {
GlUtils.glDeleteBuffers(removed, vboIds);
counter -= removed;
}
return freed;
}
static void createBuffers(int num) {
static void createBuffers(int target, int num) {
int[] mVboIds = GlUtils.glGenBuffers(num);
int t = (target == GL20.GL_ARRAY_BUFFER) ? 0 : 1;
for (int i = 0; i < num; i++) {
BufferObject bo = new BufferObject(mVboIds[i]);
bo.next = pool;
pool = bo;
BufferObject bo = new BufferObject(target, mVboIds[i]);
bo.next = pool[t];
pool[t] = bo;
}
}
static synchronized void init(int num) {
mBufferMemoryUsage = 0;
pool = null;
createBuffers(num);
counter = num;
// FIXME!!!!! pool = new BufferObject[2];
createBuffers(GL20.GL_ARRAY_BUFFER, num);
counter[0] = num;
}
}

View File

@ -137,7 +137,7 @@ public class GLRenderer {
int tmpBufferSize;
void growBuffer(int size) {
Log.d(TAG, "grow buffer " + size);
//Log.d(TAG, "grow buffer " + size);
// 32kb min size
if (size < (1 << 15))
size = (1 << 15);
@ -243,7 +243,7 @@ public class GLRenderer {
}
newSize *= SHORT_BYTES;
layers.vbo.loadBufferData(sbuf, newSize, GL20.GL_ARRAY_BUFFER);
layers.vbo.loadBufferData(sbuf, newSize);
return true;
}
@ -395,9 +395,9 @@ public class GLRenderer {
}
public void onSurfaceCreated() {
Log.d(TAG, "surface created");
// Log.d(TAG, GL.glGetString(GL20.GL_EXTENSIONS));
// classes that require GL context for initialization

View File

@ -15,7 +15,6 @@
package org.oscim.renderer.layers;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.core.MapPosition;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer;
@ -37,8 +36,6 @@ import org.oscim.view.MapView;
*/
public abstract class BasicRenderLayer extends RenderLayer {
private static final GL20 GL = GLAdapter.get();
public final Layers layers;
public BasicRenderLayer(MapView mapView) {
@ -55,7 +52,7 @@ public abstract class BasicRenderLayer extends RenderLayer {
float div = FastMath.pow(pos.zoomLevel - curPos.zoomLevel);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, layers.vbo.id);
layers.vbo.bind();
GLState.test(false, false);
GLState.blend(true);
int simple = (curPos.tilt < 1 ? 1 : 0);
@ -91,10 +88,6 @@ public abstract class BasicRenderLayer extends RenderLayer {
l = BitmapRenderer.draw(l, 1, m);
break;
// case Layer.SYMBOL:
// l = BitmapRenderer.draw(l, 1, m);
// break;
default:
l = TextureRenderer.draw(l, scale, m);
}
@ -113,7 +106,7 @@ public abstract class BasicRenderLayer extends RenderLayer {
}
if (layers.vbo == null) {
layers.vbo = BufferObject.get(newSize);
layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize);
if (layers.vbo == null)
return;

View File

@ -95,8 +95,8 @@ public class CustomRenderLayer2 extends RenderLayer {
buf.put(vertices);
buf.flip();
mVBO = BufferObject.get(0);
mVBO.loadBufferData(buf, 12 * 4, GL20.GL_ARRAY_BUFFER);
mVBO = BufferObject.get(GL20.GL_ARRAY_BUFFER, 0);
mVBO.loadBufferData(buf, 12 * 4);
newData = false;
// tell GLRender to call 'render'
@ -113,7 +113,7 @@ public class CustomRenderLayer2 extends RenderLayer {
GLState.test(false, false);
// bind VBO data
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, mVBO.id);
mVBO.bind();
// set VBO vertex layout
GL.glVertexAttribPointer(hVertexPosition, 2, GL20.GL_FLOAT, false, 0, 0);

View File

@ -14,10 +14,6 @@
*/
package org.oscim.renderer.layers;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.Log;
@ -203,8 +199,8 @@ public class ExtrusionRenderLayer extends RenderLayer {
setMatrix(pos, m, tiles[i], 0);
m.mvp.setAsUniform(uExtMatrix);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, el.vboVertices.id);
el.vboIndices.bind();
el.vboVertices.bind();
GL.glVertexAttribPointer(uExtVertexPosition, 3,
GL20.GL_SHORT, false, 8, 0);
@ -255,8 +251,8 @@ public class ExtrusionRenderLayer extends RenderLayer {
setMatrix(pos, m, t, d);
m.mvp.setAsUniform(uExtMatrix);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, el.vboVertices.id);
el.vboIndices.bind();
el.vboVertices.bind();
GL.glVertexAttribPointer(uExtVertexPosition, 3,
GL20.GL_SHORT, false, 8, 0);
@ -281,8 +277,8 @@ public class ExtrusionRenderLayer extends RenderLayer {
setMatrix(pos, m, t, d);
m.mvp.setAsUniform(uExtMatrix);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, el.vboIndices.id);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, el.vboVertices.id);
el.vboIndices.bind();
el.vboVertices.bind();
GL.glVertexAttribPointer(uExtVertexPosition, 3,
GL20.GL_SHORT, false, 8, 0);

View File

@ -28,8 +28,6 @@ package org.oscim.renderer.layers;
// 5 R-Tree might be handy
//
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Color;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
@ -56,13 +54,13 @@ import org.oscim.view.MapViewPosition;
public class TextRenderLayer extends BasicRenderLayer {
private final static String TAG = TextRenderLayer.class.getName();
private static final GL20 GL = GLAdapter.get();
//private final static String TAG = TextRenderLayer.class.getName();
//private static final GL20 GL = GLAdapter.get();
private final static float MIN_CAPTION_DIST = 5;
private final static float MIN_WAY_DIST = 3;
private final static long MAX_RELABEL_DELAY = 200;
//private final static long MAX_RELABEL_DELAY = 200;
private final MapViewPosition mMapViewPosition;
private final TileSet mTileSet;
@ -734,7 +732,7 @@ public class TextRenderLayer extends BasicRenderLayer {
@Override
public synchronized void render(MapPosition pos, Matrices m) {
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, layers.vbo.id);
layers.vbo.bind();
GLState.test(false, false);
float scale = (float) (mMapPosition.scale / pos.scale);
@ -758,7 +756,7 @@ public class TextRenderLayer extends BasicRenderLayer {
l = TextureRenderer.draw(l, scale, m);
}
private boolean mHolding;
//private boolean mHolding;
/**
* @param enable layer updates

View File

@ -15,130 +15,55 @@
package org.oscim.renderer.layers.test;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import org.oscim.view.MapView;
import org.oscim.core.MapPosition;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.RenderLayer;
import org.oscim.view.MapView;
public class ModelRenderLayer extends RenderLayer{
public ModelRenderLayer(MapView mapView) {
super(mapView);
// TODO Auto-generated constructor stub
}
@Override
public void update(MapPosition pos, boolean changed, Matrices m) {
// TODO Auto-generated method stub
}
@Override
public void compile() {
// TODO Auto-generated method stub
}
@Override
public void render(MapPosition pos, Matrices m) {
// TODO Auto-generated method stub
}
// based on edu.spsu.logo.SimpleRenderer (c) Jeff Chastine
private FloatBuffer vertexBuffer; // A buffer to hold the geometry/vertices
private FloatBuffer normalBuffer; // A buffer to hold the normals of each vertex
private FloatBuffer texCoordBuffer; // A buffer to hold the texture coordinates for each vertex
//private FloatBuffer lightBuffer; // A buffer to hold the position of a light
private void initShapes() {
float sin30 = (float)Math.sin(Math.PI/6.0);
float cos30 = (float)Math.cos(Math.PI/6.0);
float hexagonCoords[] = {
0.0f, 0.0f, 0.0f, // Hexagon face of SPSU logo
cos30, sin30, 0.0f,
0.0f, 1.0f, 0.0f,
-cos30, sin30, 0.0f,
-cos30, -sin30, 0.0f,
0.0f, -1.0f, 0.0f,
cos30, -sin30, 0.0f,
cos30, sin30, 0.0f
};
float hexagonNormals[] = {
0.0f, 0.0f, 1.0f, // Normals for each vertex
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f
};
float hexagonTexCoords[] = {
0.5f, 0.5f, // Texture coordinates for each vertex
-cos30/2.0f+0.5f, -sin30/2.0f+0.5f,
0.5f, 0.0f,
cos30/2.0f+0.5f, -sin30/2.0f+0.5f,
cos30/2.0f+0.5f, sin30/2.0f+0.5f,
0.5f, 1.0f,
-cos30/2.0f+0.5f, sin30/2.0f+0.5f,
-cos30/2.0f+0.5f, -sin30/2.0f+0.5f,
};
// Load all of that info into 3 buffers
ByteBuffer vbb = ByteBuffer.allocateDirect(hexagonCoords.length*4);
vbb.order (ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer(); // make a buffer from a buffer
vertexBuffer.put(hexagonCoords); // add the coords to the float buffer
vertexBuffer.position(0); // set the reading pointer back to 0
ByteBuffer vbb2 = ByteBuffer.allocateDirect(hexagonNormals.length*4);
vbb2.order (ByteOrder.nativeOrder());
normalBuffer = vbb2.asFloatBuffer(); // make a buffer from a buffer
normalBuffer.put(hexagonNormals); // add the coords to the float buffer
normalBuffer.position(0); // set the reading pointer back to 0
ByteBuffer vbb3 = ByteBuffer.allocateDirect(hexagonTexCoords.length*4);
vbb3.order (ByteOrder.nativeOrder());
texCoordBuffer = vbb3.asFloatBuffer(); // make a buffer from a buffer
texCoordBuffer.put(hexagonTexCoords); // add the coords to the float buffer
texCoordBuffer.position(0); // set the reading pointer back to 0
}
private final static String vertexShader = ""
+ "uniform mat4 uMVPMatrix;"
+ "uniform vec4 uLightPos;"
+ "attribute vec4 vPosition;"
+ "attribute vec4 vNormal;"
+ "attribute vec2 aTextureCoord;"
+ "varying vec2 vTextureCoord;"
+ "varying vec4 color;"
+
"void main() {"
//" vec4 normal = vNormal*uMVPMatrix;" +
+ " vec3 light = normalize (uLightPos.xyz);"
+ " vec3 normal = normalize (vNormal.xyz);"
+ " vTextureCoord = aTextureCoord;"
+ " color = vec4 (0.6, 0.8, 0.1, 1.0)*max(0.2, dot(normal, light));"
+ " gl_Position = uMVPMatrix * vPosition;"
+ "}";
private final static String fragmentShader = ""
+ "precision mediump float;"
+ "varying vec4 color;"
+ "varying vec2 vTextureCoord;"
+ "uniform sampler2D sTexture;"
+ "void main() {"
+ " gl_FragColor = color + texture2D(sTexture, vTextureCoord);"
+ "}";
// private final static String vertexShader = ""
// + "uniform mat4 uMVPMatrix;"
// + "uniform vec4 uLightPos;"
// + "attribute vec4 vPosition;"
// + "attribute vec4 vNormal;"
// + "attribute vec2 aTextureCoord;"
// + "varying vec2 vTextureCoord;"
// + "varying vec4 color;"
// +
//
// "void main() {"
// + " vec3 light = normalize (uLightPos.xyz);"
// + " vec3 normal = normalize (vNormal.xyz);"
// + " vTextureCoord = aTextureCoord;"
// + " color = vec4 (0.6, 0.8, 0.1, 1.0)*max(0.2, dot(normal, light));"
// + " gl_Position = uMVPMatrix * vPosition;"
// + "}";
//
// private final static String fragmentShader = ""
// + "precision mediump float;"
// + "varying vec4 color;"
// + "varying vec2 vTextureCoord;"
// + "uniform sampler2D sTexture;"
// + "void main() {"
// + " gl_FragColor = color + texture2D(sTexture, vTextureCoord);"
// + "}";
}

View File

@ -402,9 +402,9 @@ public class ExtrusionLayer extends Layer {
sbuf.flip();
int size = mNumIndices * 2;
vboIndices = BufferObject.get(size);
vboIndices.loadBufferData(sbuf, size, GL20.GL_ELEMENT_ARRAY_BUFFER);
vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size);
vboIndices.loadBufferData(sbuf, size);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
// upload vertices
@ -414,8 +414,8 @@ public class ExtrusionLayer extends Layer {
sbuf.flip();
size = mNumVertices * 4 * 2;
vboVertices = BufferObject.get(size);
vboVertices.loadBufferData(sbuf, size, GL20.GL_ARRAY_BUFFER);
vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size);
vboVertices.loadBufferData(sbuf, size);
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
@ -502,7 +502,8 @@ public class ExtrusionLayer extends Layer {
* @return number of triangles in io buffer
*/
public static native int triangulate(float[] points, int pos, int len, int numRings,
ShortBuffer io,
int ioffset);
ShortBuffer io, int ioffset) /*-{
return 0;
}-*/;
}