package org.oscim.renderer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import org.oscim.renderer.NativeBufferPool.BufferItem; import org.oscim.utils.pool.Inlist; import org.oscim.utils.pool.Pool; /** * Pool to retrieve temporary native buffer on GL-Thread: * This pool ensures to not use the same buffer to upload data twice * within a frame. * - 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) */ public class NativeBufferPool extends Pool<BufferItem> { static final class BufferItem extends Inlist<BufferItem> { ByteBuffer byteBuffer; ShortBuffer sBuffer; FloatBuffer fBuffer; IntBuffer iBuffer; int size; void growBuffer(int size) { //log.debug("grow buffer " + size); // 32kb min size if (size < (1 << 15)) size = (1 << 15); byteBuffer = ByteBuffer .allocateDirect(size) .order(ByteOrder.nativeOrder()); this.size = size; sBuffer = null; iBuffer = null; fBuffer = null; } } private BufferItem mUsedBuffers; @Override protected BufferItem createItem() { // unused; return null; } public BufferItem get(int size) { BufferItem b = mPool; if (b == null) { b = new BufferItem(); } else { mPool = b.next; b.next = null; } if (b.size < size) b.growBuffer(size); mUsedBuffers = Inlist.push(mUsedBuffers, b); return b; } public void releaseBuffers() { mUsedBuffers = releaseAll(mUsedBuffers); } /** * Only use on GL Thread! Get a native ShortBuffer for temporary use. */ public ShortBuffer getShortBuffer(int size) { BufferItem b = get(size * 2); if (b.sBuffer == null) { b.byteBuffer.clear(); b.sBuffer = b.byteBuffer.asShortBuffer(); } else { b.sBuffer.clear(); } return b.sBuffer; } /** * Only use on GL Thread! Get a native FloatBuffer for temporary use. */ public FloatBuffer getFloatBuffer(int size) { BufferItem b = get(size * 4); if (b.fBuffer == null) { b.byteBuffer.clear(); b.fBuffer = b.byteBuffer.asFloatBuffer(); } else { b.fBuffer.clear(); } b.fBuffer.clear(); return b.fBuffer; } /** * Only use on GL Thread! Get a native IntBuffer for temporary use. */ public IntBuffer getIntBuffer(int size) { BufferItem b = get(size * 4); if (b.iBuffer == null) { b.byteBuffer.clear(); b.iBuffer = b.byteBuffer.asIntBuffer(); } else { b.iBuffer.clear(); } return b.iBuffer; } }