package javax.media.opengl; import javax.media.opengl.*; import java.nio.*; import com.sun.opengl.impl.*; public class GLArrayDataServer extends GLArrayDataClient implements GLArrayData { // // lifetime matters // /** * Create a VBOBuffer object, using a predefined fixed function array index * and starting with a given Buffer object incl it's stride * * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. * On profile ES2 the fixed function emulation will transform these calls to * EnableVertexAttribArray and VertexAttribPointer calls, * and a predefined vertex attribute variable name will be choosen. * * @arg index The GL array index * @arg name The optional custom name for the GL array index, maybe null. * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'. * This name might be used as the shader attribute name. * @arg comps The array component number * @arg dataType The array index GL data type * @arg normalized Wheather the data shall be normalized * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, int stride, Buffer buffer, int glBufferUsage) throws GLException { GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); GLArrayDataServer ads = new GLArrayDataServer(); ads.init(name, index, comps, dataType, normalized, stride, buffer, 0, buffer.limit(), glBufferUsage, false); return ads; } /** * Create a VBOBuffer object, using a predefined fixed function array index * and starting with a new created Buffer object with initialSize size * * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. * On profile ES2 the fixed function emulation will transform these calls to * EnableVertexAttribArray and VertexAttribPointer calls, * and a predefined vertex attribute variable name will be choosen. * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, int initialSize, int glBufferUsage) throws GLException { GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); GLArrayDataServer ads = new GLArrayDataServer(); ads.init(name, index, comps, dataType, normalized, 0, null, 0, initialSize, glBufferUsage, false); return ads; } /** * Create a VBOBuffer object, using a predefined fixed function array index * and starting with a given Buffer offset incl it's stride * * This object can neither be enabled, nor rendered, since no knowledge of the buffer * itself is available. This object is only a VBO variant of GLArrayData * and cannot being drawn. * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ public static GLArrayDataServer createFixed(int index, String name, int comps, int dataType, boolean normalized, int stride, long bufferOffset) throws GLException { GLProfile.isValidateArrayDataType(index, comps, dataType, false, true); GLArrayDataServer ads = new GLArrayDataServer(); ads.init(name, index, comps, dataType, normalized, stride, null, bufferOffset, 0, -1, false); return ads; } /** * Create a VBOBuffer object, using a custom GLSL array attribute name * and starting with a new created Buffer object with initialSize size * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized, int initialSize, int glBufferUsage) throws GLException { GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true); Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, int.class }; Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType), new Boolean(normalized), new Integer(initialSize), new Integer(glBufferUsage) } ; if(GLProfile.isGL2ES2()) { return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args); } throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile()); } /** * Create a VBOBuffer object, using a custom GLSL array attribute name * and starting with a given Buffer object incl it's stride * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ public static GLArrayDataServer createGLSL(String name, int comps, int dataType, boolean normalized, int stride, Buffer buffer, int glBufferUsage) throws GLException { GLProfile.isValidateArrayDataType(-1, comps, dataType, true, true); Class[] types = new Class[]{ String.class, int.class, int.class, boolean.class, int.class, Buffer.class, int.class }; Object[] args = new Object[]{ name, new Integer(comps), new Integer(dataType), new Boolean(normalized), new Integer(stride), buffer, new Integer(glBufferUsage) } ; if(GLProfile.isGL2ES2()) { return (GLArrayDataServer) GLReflection.createInstance("com.sun.opengl.impl.glsl.GLSLArrayDataServer", types, args); } throw new GLException("GLArrayDataServer not supported for profile: "+GLProfile.getProfile()); } // // Data matters GLArrayData // public long getOffset() { return vboUsage?bufferOffset:-1; } public boolean isVBO() { return vboUsage; } // // Data and GL state modification .. // public void destroy(GL gl) { super.destroy(gl); if(vboName!=0) { int[] tmp = new int[1]; tmp[0] = vboName; gl.glDeleteBuffers(1, tmp, 0); vboName = 0; } } // // data matters // /** * Convenient way do disable the VBO behavior and * switch to client side data one * Only possible if buffer is defined. */ public void setVBOUsage(boolean vboUsage) { checkSeal(false); this.vboUsage=(null!=buffer)?vboUsage:true; } public int getBufferUsage() { return glBufferUsage; } public String toString() { return "GLArrayDataServer["+name+ ", index "+index+ ", location "+location+ ", isVertexAttribute "+isVertexAttribute+ ", dataType "+dataType+ ", bufferClazz "+clazz+ ", vertices "+getVerticeNumber()+ ", components "+components+ ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ ", initialSize "+initialSize+ ", glBufferUsage "+glBufferUsage+ ", vboUsage "+vboUsage+ ", vboName "+vboName+ ", sealed "+sealed+ ", bufferEnabled "+bufferEnabled+ ", bufferWritten "+bufferWritten+ ", buffer "+buffer+ ", offset "+bufferOffset+ "]"; } // // non public matters .. // protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data, long offset, int initialSize, int glBufferUsage, boolean isVertexAttribute) throws GLException { super.init(name, index, comps, dataType, normalized, stride, data, initialSize, isVertexAttribute); vboUsage=true; if( ! (GLProfile.isGL2ES2() && glBufferUsage==GL2ES2.GL_STREAM_DRAW) ) { switch(glBufferUsage) { case -1: // nop case GL2ES1.GL_STATIC_DRAW: case GL2ES1.GL_DYNAMIC_DRAW: break; default: throw new GLException("invalid glBufferUsage: "+glBufferUsage+":\n\t"+this); } } this.bufferOffset=offset; this.glBufferUsage = glBufferUsage; this.vboName = 0; } protected void enableBufferGLImpl(GL gl, boolean enable) { if(enable) { gl.glEnableClientState(index); bufferEnabled = true; if(vboUsage) { gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); if(!bufferWritten) { gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * getBufferCompSize(), buffer, glBufferUsage); } } switch(index) { case GL.GL_VERTEX_ARRAY: gl.glVertexPointer(this); break; case GL.GL_NORMAL_ARRAY: gl.glNormalPointer(this); break; case GL.GL_COLOR_ARRAY: gl.glColorPointer(this); break; case GL.GL_TEXTURE_COORD_ARRAY: gl.glTexCoordPointer(this); break; default: throw new GLException("invalid glArrayIndex: "+index+":\n\t"+this); } bufferWritten=true; } else { gl.glDisableClientState(index); bufferEnabled = false; } } protected void init_vbo(GL gl) { if(vboUsage && vboName==0) { int[] tmp = new int[1]; gl.glGenBuffers(1, tmp, 0); vboName = tmp[0]; } } protected long bufferOffset; protected int glBufferUsage; protected int vboName; protected boolean vboUsage; }