use a DirectByteBuffer pool in GLRenderer

This commit is contained in:
Hannes Janetzek 2013-06-25 07:23:14 +02:00
parent 75ef8f83e1
commit 52b2fadd7d
5 changed files with 101 additions and 110 deletions

View File

@ -4,7 +4,6 @@ import org.oscim.awt.AwtGraphics;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.GLAdapter;
import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
@ -26,7 +25,6 @@ public class Main {
CanvasAdapter.g = AwtGraphics.INSTANCE;
GLAdapter.INSTANCE = new GdxGLAdapter();
Tile.SIZE = 256;
GLRenderer.alwaysAllocBuffer = true;
new SharedLibraryLoader().load("vtm-jni");

View File

@ -66,9 +66,7 @@ public final class BufferObject {
mBufferMemoryUsage += newSize - size;
size = newSize;
GL.glBufferData(type, size, buf, GL20.GL_DYNAMIC_DRAW);
//GL.glBufferData(type, size, buf, GL20.GL_STATIC_DRAW);
}
//GL.glFinish();
}
public void bindArrayBuffer() {

View File

@ -14,7 +14,6 @@
*/
package org.oscim.renderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
@ -32,16 +31,16 @@ import org.oscim.renderer.sublayers.Layers;
import org.oscim.theme.IRenderTheme;
import org.oscim.utils.GlUtils;
import org.oscim.utils.Matrix4;
import org.oscim.utils.pool.Inlist;
import org.oscim.utils.pool.Pool;
import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
public class GLRenderer {
private static final String TAG = GLRenderer.class.getName();
private static final GL20 GL = GLAdapter.INSTANCE;
private static final int MB = 1024 * 1024;
private static final int SHORT_BYTES = 2;
private static final int CACHE_TILES_MAX = 250;
@ -55,11 +54,6 @@ public class GLRenderer {
private static MapViewPosition mMapViewPosition;
private static MapPosition mMapPosition;
private static ShortBuffer shortBuffer;
private static FloatBuffer floatBuffer;
private static IntBuffer intBuffer;
private static int tmpBufferSize;
private static short[] mFillCoords;
public class Matrices {
@ -73,8 +67,8 @@ public class GLRenderer {
public final Matrix4 mvp = new Matrix4();
/**
* Set MVP so that coordinates are in screen pixel coordinates
* with 0,0 being center
* Set MVP so that coordinates are in screen pixel coordinates with 0,0
* being center
*/
public void useScreenCoordinates(boolean center, float scale) {
float ratio = (1f / (scale * screenWidth));
@ -83,9 +77,9 @@ public class GLRenderer {
mvp.setScale(ratio, ratio, ratio);
else
mvp.setTransScale(
(-screenWidth / 2) * ratio * scale,
(-screenHeight / 2) * ratio * scale,
ratio);
(-screenWidth / 2) * ratio * scale,
(-screenHeight / 2) * ratio * scale,
ratio);
mvp.multiplyLhs(proj);
}
@ -93,7 +87,7 @@ public class GLRenderer {
private static Matrices mMatrices;
//private
// private
static float[] mClearColor = null;
public static int mQuadIndicesID;
@ -135,62 +129,99 @@ public class GLRenderer {
mClearColor = GlUtils.colorToFloat(t.getMapBackground());
mUpdateColor = true;
}
public static boolean alwaysAllocBuffer = false;
static class BufferItem extends Inlist<BufferItem> {
ShortBuffer shortBuffer;
FloatBuffer floatBuffer;
IntBuffer intBuffer;
int tmpBufferSize;
void growBuffer(int size) {
Log.d(TAG, "grow buffer " + size);
// 32kb min size
if (size < (1 << 15))
size = (1 << 15);
ByteBuffer buf = ByteBuffer
.allocateDirect(size)
.order(ByteOrder.nativeOrder());
this.floatBuffer = buf.asFloatBuffer();
this.shortBuffer = buf.asShortBuffer();
this.intBuffer = buf.asIntBuffer();
this.tmpBufferSize = size;
}
}
static class BufferPool extends Pool<BufferItem>{
private BufferItem mUsedBuffers;
@Override
protected BufferItem createItem() {
// unused;
return null;
}
public BufferItem get(int size){
BufferItem b = pool;
if (b == null){
b = new BufferItem();
} else {
pool = b.next;
b.next = null;
}
if (b.tmpBufferSize < size)
b.growBuffer(size);
mUsedBuffers = Inlist.push(mUsedBuffers, b);
return b;
}
public void releaseBuffers(){
mBufferPool.releaseAll(mUsedBuffers);
mUsedBuffers = null;
}
}
// Do not use the same buffer to upload data within a frame twice
// - Contrary to what the OpenGL doc says data seems *not* to be
// *always* copied after glBufferData returns...
// - Somehow it does always copy when using Android GL bindings
// but not when using libgdx bindings (LWJGL or AndroidGL20)
private static BufferPool mBufferPool = new BufferPool();
/**
* Only use on GL Thread!
* Get a native ShortBuffer for temporary use.
* Only use on GL Thread! Get a native ShortBuffer for temporary use.
*/
public static ShortBuffer getShortBuffer(int size) {
if (alwaysAllocBuffer || tmpBufferSize < size * 2)
growBuffer(size * 2);
else
shortBuffer.clear();
return shortBuffer;
BufferItem b = mBufferPool.get(size * 2);
b.shortBuffer.clear();
return b.shortBuffer;
}
/**
* Only use on GL Thread!
* Get a native FloatBuffer for temporary use.
* Only use on GL Thread! Get a native FloatBuffer for temporary use.
*/
public static FloatBuffer getFloatBuffer(int size) {
if (alwaysAllocBuffer || tmpBufferSize < size * 4)
growBuffer(size * 4);
else
floatBuffer.clear();
return floatBuffer;
BufferItem b = mBufferPool.get(size * 4);
b.floatBuffer.clear();
return b.floatBuffer;
}
/**
* Only use on GL Thread!
* Get a native IntBuffer for temporary use.
* Only use on GL Thread! Get a native IntBuffer for temporary use.
*/
public static IntBuffer getIntBuffer(int size) {
if (alwaysAllocBuffer || tmpBufferSize < size * 4)
growBuffer(size * 4);
else
intBuffer.clear();
return intBuffer;
}
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();
intBuffer = buf.asIntBuffer();
tmpBufferSize = size;
BufferItem b = mBufferPool.get(size * 4);
b.intBuffer.clear();
return b.intBuffer;
}
public static boolean uploadLayers(Layers layers, int newSize,
boolean addFill) {
boolean addFill) {
// add fill coordinates
if (addFill)
newSize += 8;
@ -205,10 +236,10 @@ public class GLRenderer {
if (newSize != sbuf.remaining()) {
Log.d(TAG, "wrong size: "
+ " new size: " + newSize
+ " buffer pos: " + sbuf.position()
+ " buffer limit: " + sbuf.limit()
+ " buffer fill: " + sbuf.remaining());
+ " new size: " + newSize
+ " buffer pos: " + sbuf.position()
+ " buffer limit: " + sbuf.limit()
+ " buffer fill: " + sbuf.remaining());
return false;
}
newSize *= SHORT_BYTES;
@ -217,17 +248,7 @@ public class GLRenderer {
return true;
}
//private long lastDraw = 0;
public void onDrawFrame() {
//long start = SystemClock.uptimeMillis();
//long wait = 30 - (start - lastDraw);
//if (wait > 5) {
// //Log.d(TAG, "wait " + wait);
// SystemClock.sleep(wait);
// lastDraw = start + wait;
//} else
// lastDraw = start;
// prevent main thread recreating all tiles (updateMap)
// while rendering is going on.
@ -237,13 +258,11 @@ public class GLRenderer {
} finally {
drawlock.unlock();
}
mBufferPool.releaseBuffers();
}
private static void draw() {
//long start = 0;
//if (MapView.debugFrameTime)
// start = SystemClock.uptimeMillis();
if (mUpdateColor) {
float cc[] = mClearColor;
@ -254,8 +273,8 @@ public class GLRenderer {
GL.glDepthMask(true);
GL.glStencilMask(0xFF);
GL.glClear(GL20.GL_COLOR_BUFFER_BIT
| GL20.GL_DEPTH_BUFFER_BIT
| GL20.GL_STENCIL_BUFFER_BIT);
| GL20.GL_DEPTH_BUFFER_BIT
| GL20.GL_STENCIL_BUFFER_BIT);
boolean changed = false;
@ -302,14 +321,9 @@ public class GLRenderer {
renderLayer.render(mMapPosition, mMatrices);
}
//if (MapView.debugFrameTime) {
// GL.glFinish();
// Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
//}
if (GlUtils.checkGlOutOfMemory("finish")) {
BufferObject.checkBufferUsage(true);
// TODO also throw out some textures etc
// FIXME also throw out some textures etc
}
}
@ -344,8 +358,6 @@ public class GLRenderer {
GL.glDisable(GL20.GL_CULL_FACE);
GL.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
//mBufferMemoryUsage = 0;
if (!mNewSurface) {
mMapView.updateMap(false);
return;
@ -353,9 +365,6 @@ public class GLRenderer {
mNewSurface = false;
// set initial temp buffer size
growBuffer(MB >> 2);
// upload quad indices used by Texture- and LineTexRenderer
int[] vboIds = GlUtils.glGenBuffers(1);
@ -371,14 +380,14 @@ public class GLRenderer {
indices[i + 4] = (short) (j + 1);
indices[i + 5] = (short) (j + 3);
}
GLRenderer.getShortBuffer(indices.length);
shortBuffer.put(indices);
shortBuffer.flip();
ShortBuffer buf = GLRenderer.getShortBuffer(indices.length);
buf.put(indices);
buf.flip();
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER,
mQuadIndicesID);
mQuadIndicesID);
GL.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER,
indices.length * 2, shortBuffer, GL20.GL_STATIC_DRAW);
indices.length * 2, buf, GL20.GL_STATIC_DRAW);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
if (mClearColor != null)
@ -404,8 +413,4 @@ public class GLRenderer {
private boolean mNewSurface;
public static final boolean debugView = false;
// void clearBuffer() {
// mNewSurface = true;
// }
}

View File

@ -64,16 +64,6 @@ public class ExtrusionRenderLayer extends RenderLayer {
private final static int SHADER = 0;
private static ShortBuffer getShortBuffer(int size) {
ByteBuffer buf = ByteBuffer
.allocateDirect(size)
.order(ByteOrder.nativeOrder());
return buf.asShortBuffer();
}
private boolean initShader() {
initialized = true;
@ -134,8 +124,8 @@ public class ExtrusionRenderLayer extends RenderLayer {
continue;
if (!el.compiled) {
int bytes = el.mNumVertices * 8 * 2;
el.compile(getShortBuffer(bytes));
int numShorts = el.mNumVertices * 8;
el.compile(GLRenderer.getShortBuffer(numShorts));
GlUtils.checkGlError("...");
}

View File

@ -16,7 +16,7 @@ package org.oscim.utils.pool;
public abstract class Pool<T extends Inlist<T>> {
T pool;
protected T pool;
/**
* @param item release resources