package org.anddev.andengine.opengl.buffer; import javax.microedition.khronos.opengles.GL11; import org.anddev.andengine.opengl.util.FastFloatBuffer; import org.anddev.andengine.opengl.util.GLHelper; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 14:22:56 - 07.04.2010 */ public abstract class BufferObject { // =========================================================== // Constants // =========================================================== private static final int[] HARDWAREBUFFERID_FETCHER = new int[1]; // =========================================================== // Fields // =========================================================== protected final int[] mBufferData; private final int mDrawType; protected final FastFloatBuffer mFloatBuffer; private int mHardwareBufferID = -1; private boolean mLoadedToHardware; private boolean mHardwareBufferNeedsUpdate = true; private boolean mManaged; // =========================================================== // Constructors // =========================================================== /** * @param pCapacity * @param pDrawType * @param pManaged when passing <code>true</code> this {@link BufferObject} loads itself to the active {@link BufferObjectManager}. <b><u>WARNING:</u></b> When passing <code>false</code> one needs to take care of that by oneself! */ public BufferObject(final int pCapacity, final int pDrawType, final boolean pManaged) { this.mDrawType = pDrawType; this.mManaged = pManaged; this.mBufferData = new int[pCapacity]; this.mFloatBuffer = new FastFloatBuffer(pCapacity); if(pManaged) { this.loadToActiveBufferObjectManager(); } } // =========================================================== // Getter & Setter // =========================================================== public boolean isManaged() { return this.mManaged; } public void setManaged(final boolean pManaged) { this.mManaged = pManaged; } public FastFloatBuffer getFloatBuffer() { return this.mFloatBuffer; } public int getHardwareBufferID() { return this.mHardwareBufferID; } public boolean isLoadedToHardware() { return this.mLoadedToHardware; } void setLoadedToHardware(final boolean pLoadedToHardware) { this.mLoadedToHardware = pLoadedToHardware; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== public void setHardwareBufferNeedsUpdate(){ this.mHardwareBufferNeedsUpdate = true; } // =========================================================== // Methods // =========================================================== public void selectOnHardware(final GL11 pGL11) { final int hardwareBufferID = this.mHardwareBufferID; if(hardwareBufferID == -1) { return; } GLHelper.bindBuffer(pGL11, hardwareBufferID); // TODO Does this always need to be bound, or are just for buffers of the same 'type'(texture/vertex)? if(this.mHardwareBufferNeedsUpdate) { this.mHardwareBufferNeedsUpdate = false; synchronized(this) { GLHelper.bufferData(pGL11, this.mFloatBuffer.mByteBuffer, this.mDrawType); } } } public void loadToActiveBufferObjectManager() { BufferObjectManager.getActiveInstance().loadBufferObject(this); } public void unloadFromActiveBufferObjectManager() { BufferObjectManager.getActiveInstance().unloadBufferObject(this); } public void loadToHardware(final GL11 pGL11) { this.mHardwareBufferID = this.generateHardwareBufferID(pGL11); this.mLoadedToHardware = true; } public void unloadFromHardware(final GL11 pGL11) { this.deleteBufferOnHardware(pGL11); this.mHardwareBufferID = -1; this.mLoadedToHardware = false; } private void deleteBufferOnHardware(final GL11 pGL11) { GLHelper.deleteBuffer(pGL11, this.mHardwareBufferID); } private int generateHardwareBufferID(final GL11 pGL11) { pGL11.glGenBuffers(1, HARDWAREBUFFERID_FETCHER, 0); return HARDWAREBUFFERID_FETCHER[0]; } // =========================================================== // Inner and Anonymous Classes // =========================================================== }