diff options
author | Sven Gothel <[email protected]> | 2014-01-21 18:51:16 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-01-21 18:51:16 +0100 |
commit | 343deff48d81b0abf58c275d9e0aced12a911802 (patch) | |
tree | 42425be7def0fa9af9b25ca879c37e5f7f70c7ad | |
parent | 09fc7aa5539731bb0fba835caee61f6eb837ecff (diff) |
Bug 942: GLBufferObjectTracker Enhancement [2/2]: Add mapped buffer capabilities to GLArrayDataServer and add unit tests
GLArrayDataServer:
- Add create*Mapped(..) variants for GPU mapped buffer usage
w/o client buffers.
- Fix API documentation (arguments)
- Fix 'addGLSLSubArray(..)'
- properly compute and pass 'subStrideB' in bytes to GLArrayDataWrapper ctor.
- Add 'mapStorage(..)' and 'unmapStorage(..)'
allowing to map the GPU buffer.
GLArrayDataWrapper:
- Fix getElementCount(): Consider stride in bytes and consider 'mappedElementCount'
- getSizeInBytes(): Consider 'mappedElementCount'
Tests:
- Use new GLBase methods, e.g. getBoundBuffer(..) instead of glGetBoundBuffer(..)
- TestMapBufferRead01NEWT: Validate GLBufferStorage (i.e. GLBufferObjectTracker)
- Add RedSquareMappedES2 using GPU mapped buffer
- Test w/ TestRedSquareES2NEWT, cmd-line 'mappedBuffers'
- GearsES1 and GearsES2: Add GPU buffer mapping mode for all test cases
- Add buffer validation mode, i.e. test whether GLBufferObjectTracker
works properly.
- Test w/ TestGearsES2NEWT, cmd-line 'mappedBuffers'
- TestSharedContextVBOES2NEWT0, TestSharedContextVBOES2NEWT3:
- Add GPU mapped buffers tests to validate GLBufferObjectTracker
code path with shared GLContext across multiple threads.
16 files changed, 993 insertions, 289 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java index f84342e88..a58eb82cd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -74,7 +74,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData { GLArrayDataClient adc = new GLArrayDataClient(); GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc); - adc.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, false, glArrayHandler, 0, 0, 0, 0, false); + adc.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, glArrayHandler, 0, 0, 0, 0, false); return adc; } @@ -105,7 +105,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData { GLArrayDataClient adc = new GLArrayDataClient(); GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc); - adc.init(null, index, comps, dataType, normalized, stride, buffer, comps*comps, false, glArrayHandler, 0, 0, 0, 0, false); + adc.init(null, index, comps, dataType, normalized, stride, buffer, comps*comps, 0 /* mappedElementCount */, false, glArrayHandler, 0, 0, 0, 0, false); return adc; } @@ -124,7 +124,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData { GLArrayDataClient adc = new GLArrayDataClient(); GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc); - adc.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount, true, glArrayHandler, 0, 0, 0, 0, true); + adc.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, 0, 0, true); return adc; } @@ -144,7 +144,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData { GLArrayDataClient adc = new GLArrayDataClient(); GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc); - adc.init(name, -1, comps, dataType, normalized, stride, buffer, comps*comps, true, glArrayHandler, 0, 0, 0, 0, true); + adc.init(name, -1, comps, dataType, normalized, stride, buffer, comps*comps, 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, 0, 0, true); return adc; } @@ -177,7 +177,9 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // @Override - public final void setVBOWritten(boolean written) { bufferWritten=written; } + public final void setVBOWritten(boolean written) { + bufferWritten = ( 0 == mappedElementCount ) ? written : true; + } @Override public void destroy(GL gl) { @@ -231,25 +233,25 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData @Override public void reset() { - if(buffer!=null) { + if( buffer != null ) { buffer.clear(); } - this.sealed=false; - this.bufferEnabled=false; - this.bufferWritten=false; + sealed = false; + bufferEnabled = false; + bufferWritten = ( 0 == mappedElementCount ) ? false : true; } @Override public void seal(boolean seal) { - if(sealed==seal) return; + if( sealed == seal ) return; sealed = seal; - bufferWritten=false; - if(seal) { - if (null!=buffer) { + bufferWritten = ( 0 == mappedElementCount ) ? false : true; + if( seal ) { + if ( null != buffer ) { buffer.flip(); } - } else if (null!=buffer) { + } else if ( null != buffer ) { buffer.position(buffer.limit()); buffer.limit(buffer.capacity()); } @@ -333,8 +335,9 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ - ", components "+components+ + ", components "+componentsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ + ", mappedElementCount "+mappedElementCount+ ", initialElementCount "+initialElementCount+ ", sealed "+sealed+ ", bufferEnabled "+bufferEnabled+ @@ -346,9 +349,14 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // non public matters - protected final boolean growBufferIfNecessary(int spare) { - if(buffer==null || buffer.remaining()<spare) { - growBuffer(Math.max(initialElementCount, spare)); + protected final boolean growBufferIfNecessary(int spareComponents) { + if( buffer==null || buffer.remaining()<spareComponents ) { + if( 0 != mappedElementCount ) { + throw new GLException("Mapped buffer can't grow. Insufficient storage size: Needed "+spareComponents+" components, "+ + "mappedElementCount "+mappedElementCount+ + ", has mapped buffer "+buffer+"; "+this); + } + growBuffer(Math.max(initialElementCount, (spareComponents+componentsPerElement-1)/componentsPerElement)); return true; } return false; @@ -360,34 +368,35 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } // add the stride delta - additionalElements += (additionalElements/components)*(strideL-components); + additionalElements += (additionalElements/componentsPerElement)*(strideL-componentsPerElement); final int osize = (buffer!=null) ? buffer.capacity() : 0; - final int nsize = osize + ( additionalElements * components ); + final int nsize = osize + ( additionalElements * componentsPerElement ); + final Buffer oldBuffer = buffer; if(componentClazz==ByteBuffer.class) { - ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( nsize ); + final ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( nsize ); if(buffer!=null) { buffer.flip(); newBBuffer.put((ByteBuffer)buffer); } buffer = newBBuffer; } else if(componentClazz==ShortBuffer.class) { - ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( nsize ); + final ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( nsize ); if(buffer!=null) { buffer.flip(); newSBuffer.put((ShortBuffer)buffer); } buffer = newSBuffer; } else if(componentClazz==IntBuffer.class) { - IntBuffer newIBuffer = Buffers.newDirectIntBuffer( nsize ); + final IntBuffer newIBuffer = Buffers.newDirectIntBuffer( nsize ); if(buffer!=null) { buffer.flip(); newIBuffer.put((IntBuffer)buffer); } buffer = newIBuffer; } else if(componentClazz==FloatBuffer.class) { - FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( nsize ); + final FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( nsize ); if(buffer!=null) { buffer.flip(); newFBuffer.put((FloatBuffer)buffer); @@ -397,7 +406,8 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this); } if(DEBUG) { - System.err.println("*** Grow: comps: "+components+", "+(osize/components)+"/"+osize+" -> "+(nsize/components)+"/"+nsize+", "+this); + System.err.println("*** Grow: comps: "+componentsPerElement+", "+(osize/componentsPerElement)+"/"+osize+" -> "+(nsize/componentsPerElement)+"/"+nsize+ + "; "+oldBuffer+" -> "+buffer+"; "+this); } } @@ -415,20 +425,24 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData } protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data, - int initialElementCount, boolean isVertexAttribute, GLArrayHandler handler, - int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL) + int initialElementCount, int mappedElementCount, boolean isVertexAttribute, + GLArrayHandler handler, int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL) throws GLException { - super.init(name, index, comps, dataType, normalized, stride, data, isVertexAttribute, - vboName, vboOffset, vboUsage, vboTarget); + super.init(name, index, comps, dataType, normalized, stride, data, mappedElementCount, + isVertexAttribute, vboName, vboOffset, vboUsage, vboTarget); + if( 0<mappedElementCount && 0<initialElementCount ) { // null!=buffer case validated in super.init(..) + throw new IllegalArgumentException("mappedElementCount:="+mappedElementCount+" specified, but passing non zero initialElementSize"); + } this.initialElementCount = initialElementCount; this.glArrayHandler = handler; this.usesGLSL = usesGLSL; this.sealed=false; this.bufferEnabled=false; this.enableBufferAlways=false; - this.bufferWritten=false; + this.bufferWritten = ( 0 == mappedElementCount ) ? false : true; + if(null==buffer && initialElementCount>0) { growBuffer(initialElementCount); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java index 4a12ff1ae..833f1ccda 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java @@ -29,11 +29,15 @@ package com.jogamp.opengl.util; import java.nio.Buffer; +import java.nio.ByteBuffer; import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLArrayData; +import javax.media.opengl.GLBufferStorage; import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLPointerFuncUtil; @@ -68,23 +72,23 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}. * * @param index The GL array index - * @param comps The array component number - * @param dataType The array index GL data type + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param stride + * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes * @param buffer the user define data * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ - public static GLArrayDataServer createFixed(int index, int comps, int dataType, boolean normalized, int stride, + public static GLArrayDataServer createFixed(int index, int compsPerElement, int dataType, boolean normalized, int stride, Buffer buffer, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); - ads.init(null, index, comps, dataType, normalized, stride, buffer, buffer.limit(), false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + ads.init(null, index, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); return ads; } @@ -101,22 +105,22 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}. * * @param index The GL array index - * @param comps The array component number - * @param dataType The array index GL data type + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized * @param initialElementCount * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} * * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) */ - public static GLArrayDataServer createFixed(int index, int comps, int dataType, boolean normalized, int initialElementCount, + public static GLArrayDataServer createFixed(int index, int compsPerElement, int dataType, boolean normalized, int initialElementCount, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); - ads.init(null, index, comps, dataType, normalized, 0, null, initialElementCount, false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + ads.init(null, index, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); return ads; } @@ -124,20 +128,42 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * Create a VBO, using a custom GLSL array attribute name * and starting with a new created Buffer object with initialElementCount size * @param name The custom name for the GL attribute - * @param comps The array component number - * @param dataType The array index GL data type + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized * @param initialElementCount * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createGLSL(String name, int comps, + public static GLArrayDataServer createGLSL(String name, int compsPerElement, int dataType, boolean normalized, int initialElementCount, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); - ads.init(name, -1, comps, dataType, normalized, 0, null, initialElementCount, - true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount, + 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + return ads; + } + + /** + * Create a VBO, using a custom GLSL array attribute name + * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. + * @param name The custom name for the GL attribute + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type + * @param normalized Whether the data shall be normalized + * @param mappedElementCount + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + */ + public static GLArrayDataServer createGLSLMapped(String name, int compsPerElement, + int dataType, boolean normalized, int mappedElementCount, int vboUsage) + throws GLException + { + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); + ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */, + mappedElementCount, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.seal(true); return ads; } @@ -145,22 +171,22 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * Create a VBO, using a custom GLSL array attribute name * and starting with a given Buffer object incl it's stride * @param name The custom name for the GL attribute - * @param comps The array component number - * @param dataType The array index GL data type + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param stride + * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes * @param buffer the user define data * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createGLSL(String name, int comps, + public static GLArrayDataServer createGLSL(String name, int compsPerElement, int dataType, boolean normalized, int stride, Buffer buffer, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); - ads.init(name, -1, comps, dataType, normalized, stride, buffer, buffer.limit(), true, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.init(name, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, true, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); return ads; } @@ -169,22 +195,22 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * * Hence no index, name for a fixed function pipeline nor vertex attribute is given. * - * @param comps The array component number - * @param dataType The array index GL data type - * @param stride + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type + * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes * @param buffer the user define data * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. * {@link GL#glGenBuffers(int, int[], int) */ - public static GLArrayDataServer createData(int comps, int dataType, int stride, + public static GLArrayDataServer createData(int compsPerElement, int dataType, int stride, Buffer buffer, int vboUsage, int vboTarget) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); - ads.init(null, -1, comps, dataType, false, stride, buffer, buffer.limit(), false, glArrayHandler, - 0, 0, vboUsage, vboTarget, false); + ads.init(null, -1, compsPerElement, dataType, false, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, vboTarget, false); return ads; } @@ -193,43 +219,89 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * * Hence no index, name for a fixed function pipeline nor vertex attribute is given. * - * @param comps The array component number - * @param dataType The array index GL data type + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type * @param initialElementCount * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. */ - public static GLArrayDataServer createData(int comps, int dataType, int initialElementCount, + public static GLArrayDataServer createData(int compsPerElement, int dataType, int initialElementCount, int vboUsage, int vboTarget) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); - ads.init(null, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler, - 0, 0, vboUsage, vboTarget, false); + ads.init(null, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, vboTarget, false); return ads; } + /** + * Create a VBO data object for any target w/o render pipeline association, i.e. {@link GL#GL_ELEMENT_ARRAY_BUFFER}, + * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. + * <p> + * No index, name for a fixed function pipeline nor vertex attribute is given. + * </p> + * + * @param compsPerElement component count per element + * @param dataType The component's OpenGL data type + * @param initialElementCount + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. + */ + public static GLArrayDataServer createDataMapped(int compsPerElement, int dataType, int mappedElementCount, + int vboUsage, int vboTarget) + throws GLException + { + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); + ads.init(null, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false, + glArrayHandler, 0, 0, vboUsage, vboTarget, false); + return ads; + } /** * Create a VBO for fixed function interleaved array data * starting with a new created Buffer object with initialElementCount size. * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> * - * @param comps The total number of all interleaved components. - * @param dataType The array index GL data type + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param initialElementCount + * @param initialElementCount The initial number of all interleaved elements * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createFixedInterleaved(int comps, int dataType, boolean normalized, int initialElementCount, + public static GLArrayDataServer createFixedInterleaved(int compsPerElement, int dataType, boolean normalized, int initialElementCount, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); - ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + return ads; + } + + /** + * Create a VBO for fixed function interleaved array data + * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. + * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> + * + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type + * @param normalized Whether the data shall be normalized + * @param mappedElementCount The total number of all interleaved elements + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + */ + public static GLArrayDataServer createFixedInterleavedMapped(int compsPerElement, int dataType, boolean normalized, int mappedElementCount, + int vboUsage) + throws GLException + { + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + ads.seal(true); return ads; } @@ -238,20 +310,21 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * starting with a given Buffer object incl it's stride * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> * - * @param comps The total number of all interleaved components. - * @param dataType The array index GL data type + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param initialElementCount + * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes + * @param buffer The user define data of all interleaved elements * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createFixedInterleaved(int comps, int dataType, boolean normalized, int stride, Buffer buffer, + public static GLArrayDataServer createFixedInterleaved(int compsPerElement, int dataType, boolean normalized, int stride, Buffer buffer, int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); - ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, normalized, stride, buffer, buffer.limit(), false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); return ads; } @@ -259,14 +332,14 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * Configure a segment of this fixed function interleaved array (see {@link #createFixedInterleaved(int, int, boolean, int, int)}). * <p> * This method may be called several times as long the sum of interleaved components does not - * exceed the total number of components of the created interleaved array.</p> + * exceed the total component count of the created interleaved array.</p> * <p> * The memory of the the interleaved array is being used.</p> * <p> * Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p> * * @param index The GL array index, maybe -1 if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} - * @param comps This interleaved array segment's component number + * @param comps This interleaved array segment's component count per element * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} */ public GLArrayData addFixedSubArray(int index, int comps, int vboTarget) { @@ -277,10 +350,19 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE if(usesGLSL) { throw new GLException("buffer uses GLSL"); } - final GLArrayDataWrapper ad = GLArrayDataWrapper.createFixed( - index, comps, getComponentType(), - getNormalized(), getStride(), getBuffer(), - getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride(); + final GLArrayDataWrapper ad; + if( 0 < mappedElementCount ) { + ad = GLArrayDataWrapper.createFixed( + index, comps, getComponentType(), + getNormalized(), subStrideB, mappedElementCount, + getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + } else { + ad = GLArrayDataWrapper.createFixed( + index, comps, getComponentType(), + getNormalized(), subStrideB, getBuffer(), + getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + } ad.setVBOEnabled(isVBO()); interleavedOffset += comps * getComponentSizeInBytes(); if(GL.GL_ARRAY_BUFFER == vboTarget) { @@ -294,20 +376,42 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * starting with a new created Buffer object with initialElementCount size. * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> * - * @param comps The total number of all interleaved components. - * @param dataType The array index GL data type + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param initialElementCount + * @param initialElementCount The initial number of all interleaved elements * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createGLSLInterleaved(int comps, int dataType, boolean normalized, int initialElementCount, - int vboUsage) + public static GLArrayDataServer createGLSLInterleaved(int compsPerElement, int dataType, boolean normalized, int initialElementCount, + int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); - ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, false, 0, null, initialElementCount, false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + return ads; + } + + /** + * Create a VBO for GLSL interleaved array data + * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. + * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> + * + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type + * @param normalized Whether the data shall be normalized + * @param mappedElementCount The total number of all interleaved elements + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + */ + public static GLArrayDataServer createGLSLInterleavedMapped(int compsPerElement, int dataType, boolean normalized, int mappedElementCount, int vboUsage) + throws GLException + { + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */, mappedElementCount, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.seal(true); return ads; } @@ -316,21 +420,21 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * starting with a given Buffer object incl it's stride * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> * - * @param comps The total number of all interleaved components. - * @param dataType The array index GL data type + * @param compsPerElement The total number of all interleaved components per element. + * @param dataType The component's OpenGL data type * @param normalized Whether the data shall be normalized - * @param stride - * @param buffer the user define data + * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes + * @param buffer The user define data of all interleaved elements * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} */ - public static GLArrayDataServer createGLSLInterleaved(int comps, int dataType, boolean normalized, int stride, Buffer buffer, - int vboUsage) + public static GLArrayDataServer createGLSLInterleaved(int compsPerElement, int dataType, boolean normalized, int stride, Buffer buffer, + int vboUsage) throws GLException { GLArrayDataServer ads = new GLArrayDataServer(); GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); - ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, comps, dataType, normalized, stride, buffer, buffer.limit(), false, glArrayHandler, - 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); + ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, + glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); return ads; } @@ -338,13 +442,13 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * Configure a segment of this GLSL interleaved array (see {@link #createGLSLInterleaved(int, int, boolean, int, int)}). * <p> * This method may be called several times as long the sum of interleaved components does not - * exceed the total number of components of the created interleaved array.</p> + * exceed the total component count of the created interleaved array.</p> * <p> * The memory of the the interleaved array is being used.</p> * <p> * Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p> * @param name The custom name for the GL attribute, maybe null if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} - * @param comps This interleaved array segment's component number + * @param comps This interleaved array segment's component count per element * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} */ public GLArrayData addGLSLSubArray(String name, int comps, int vboTarget) { @@ -355,10 +459,19 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE if(!usesGLSL) { throw new GLException("buffer uses fixed function"); } - final GLArrayDataWrapper ad = GLArrayDataWrapper.createGLSL( - name, comps, getComponentType(), - getNormalized(), getStride(), getBuffer(), - getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride(); + final GLArrayDataWrapper ad; + if( 0 < mappedElementCount ) { + ad = GLArrayDataWrapper.createGLSL( + name, comps, getComponentType(), + getNormalized(), subStrideB, mappedElementCount, + getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + } else { + ad = GLArrayDataWrapper.createGLSL( + name, comps, getComponentType(), + getNormalized(), subStrideB, getBuffer(), + getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); + } ad.setVBOEnabled(isVBO()); interleavedOffset += comps * getComponentSizeInBytes(); if(GL.GL_ARRAY_BUFFER == vboTarget) { @@ -407,11 +520,73 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE * Only possible if buffer is defined. */ @Override - public void setVBOEnabled(boolean vboUsage) { + public void setVBOEnabled(boolean vboUsage) { checkSeal(false); super.setVBOEnabled(vboUsage); } + public GLBufferStorage mapStorage(GL gl, int access) { + if( null != this.getBuffer() ) { + throw new IllegalStateException("user buffer not null"); + } + if( null != mappedStorage ) { + throw new IllegalStateException("already mapped: "+mappedStorage); + } + checkSeal(true); + bindBuffer(gl, true); + gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); + final GLBufferStorage storage = gl.mapBuffer(getVBOTarget(), access); + setMappedBuffer(storage); + bindBuffer(gl, false); + seal(false); + rewind(); + return storage; + } + public GLBufferStorage mapStorage(GL gl, long offset, long length, int access) { + if( null != this.getBuffer() ) { + throw new IllegalStateException("user buffer not null"); + } + if( null != mappedStorage ) { + throw new IllegalStateException("already mapped: "+mappedStorage); + } + checkSeal(true); + bindBuffer(gl, true); + gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); + final GLBufferStorage storage = gl.mapBufferRange(getVBOTarget(), offset, length, access); + setMappedBuffer(storage); + bindBuffer(gl, false); + seal(false); + rewind(); + return storage; + } + private final void setMappedBuffer(GLBufferStorage storage) { + mappedStorage = storage; + final ByteBuffer bb = storage.getMappedBuffer(); + if(componentClazz==ByteBuffer.class) { + buffer = bb; + } else if(componentClazz==ShortBuffer.class) { + buffer = bb.asShortBuffer(); + } else if(componentClazz==IntBuffer.class) { + buffer = bb.asIntBuffer(); + } else if(componentClazz==FloatBuffer.class) { + buffer = bb.asFloatBuffer(); + } else { + throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this); + } + } + + public void unmapStorage(GL gl) { + if( null == mappedStorage ) { + throw new IllegalStateException("not mapped"); + } + mappedStorage = null; + buffer = null; + seal(true); + bindBuffer(gl, true); + gl.glUnmapBuffer(getVBOTarget()); + bindBuffer(gl, false); + } + @Override public String toString() { return "GLArrayDataServer["+name+ @@ -423,9 +598,11 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ - ", components "+components+ + ", components "+componentsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ ", initialElementCount "+initialElementCount+ + ", mappedElementCount "+mappedElementCount+ + ", mappedStorage "+mappedStorage+ ", vboEnabled "+vboEnabled+ ", vboName "+vboName+ ", vboUsage 0x"+Integer.toHexString(vboUsage)+ @@ -445,13 +622,13 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE @Override protected void init(String name, int index, int comps, int dataType, boolean normalized, - int stride, Buffer data, int initialElementCount, boolean isVertexAttribute, - GLArrayHandler glArrayHandler, - int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL) + int stride, Buffer data, int initialElementCount, int mappedElementCount, + boolean isVertexAttribute, + GLArrayHandler glArrayHandler, int vboName, long vboOffset, int vboUsage, int vboTarget, boolean usesGLSL) throws GLException { - super.init(name, index, comps, dataType, normalized, stride, data, initialElementCount, isVertexAttribute, glArrayHandler, - vboName, vboOffset, vboUsage, vboTarget, usesGLSL); + super.init(name, index, comps, dataType, normalized, stride, data, initialElementCount, mappedElementCount, isVertexAttribute, + glArrayHandler, vboName, vboOffset, vboUsage, vboTarget, usesGLSL); vboEnabled=true; } @@ -483,8 +660,10 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE public GLArrayDataServer(GLArrayDataServer src) { super(src); this.interleavedOffset = src.interleavedOffset; + this.mappedStorage = src.mappedStorage; } private int interleavedOffset = 0; + private GLBufferStorage mappedStorage = null; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java index 068ab5203..f617fed73 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -71,8 +71,35 @@ public class GLArrayDataWrapper implements GLArrayData { throws GLException { GLArrayDataWrapper adc = new GLArrayDataWrapper(); - adc.init(null, index, comps, dataType, normalized, stride, buffer, false, - vboName, vboOffset, vboUsage, vboTarget); + adc.init(null, index, comps, dataType, normalized, stride, buffer, 0 /* mappedElementCount */, + false, vboName, vboOffset, vboUsage, vboTarget); + return adc; + } + + /** + * Create a VBO, using a predefined fixed function array index, wrapping the mapped data characteristics. + * + * @param index The GL array index + * @param comps The array component number + * @param dataType The array index GL data type + * @param normalized Whether the data shall be normalized + * @param stride + * @param mappedElementCount + * @param vboName + * @param vboOffset + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} + * @return the new create instance + * + * @throws GLException + */ + public static GLArrayDataWrapper createFixed(int index, int comps, int dataType, boolean normalized, int stride, + int mappedElementCount, int vboName, long vboOffset, int vboUsage, int vboTarget) + throws GLException + { + GLArrayDataWrapper adc = new GLArrayDataWrapper(); + adc.init(null, index, comps, dataType, normalized, stride, null, mappedElementCount, + false, vboName, vboOffset, vboUsage, vboTarget); return adc; } @@ -97,8 +124,34 @@ public class GLArrayDataWrapper implements GLArrayData { throws GLException { GLArrayDataWrapper adc = new GLArrayDataWrapper(); - adc.init(name, -1, comps, dataType, normalized, stride, buffer, true, - vboName, vboOffset, vboUsage, vboTarget); + adc.init(name, -1, comps, dataType, normalized, stride, buffer, 0 /* mappedElementCount */, + true, vboName, vboOffset, vboUsage, vboTarget); + return adc; + } + + /** + * Create a VBO, using a custom GLSL array attribute name, wrapping the mapped data characteristics. + * + * @param name The custom name for the GL attribute, maybe null if gpuBufferTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} + * @param comps The array component number + * @param dataType The array index GL data type + * @param normalized Whether the data shall be normalized + * @param stride + * @param mappedElementCount + * @param vboName + * @param vboOffset + * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} + * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} + * @return the new create instance + * @throws GLException + */ + public static GLArrayDataWrapper createGLSL(String name, int comps, int dataType, boolean normalized, int stride, + int mappedElementCount, int vboName, long vboOffset, int vboUsage, int vboTarget) + throws GLException + { + GLArrayDataWrapper adc = new GLArrayDataWrapper(); + adc.init(name, -1, comps, dataType, normalized, stride, null, mappedElementCount, + true, vboName, vboOffset, vboUsage, vboTarget); return adc; } @@ -179,10 +232,10 @@ public class GLArrayDataWrapper implements GLArrayData { public final int getVBOTarget() { return vboEnabled?vboTarget:0; } @Override - public final Buffer getBuffer() { return buffer; } + public Buffer getBuffer() { return buffer; } @Override - public final int getComponentCount() { return components; } + public final int getComponentCount() { return componentsPerElement; } @Override public final int getComponentType() { return componentType; } @@ -192,14 +245,25 @@ public class GLArrayDataWrapper implements GLArrayData { @Override public final int getElementCount() { - if(null==buffer) return 0; - return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ; + if( 0 != mappedElementCount ) { + return mappedElementCount; + } else if( null != buffer ) { + final int remainingComponents = ( 0 == buffer.position() ) ? buffer.limit() : buffer.position(); + return ( remainingComponents * componentByteSize ) / strideB ; + } else { + return 0; + } } @Override public final int getSizeInBytes() { - if(null==buffer) return 0; - return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ; + if( 0 != mappedElementCount ) { + return mappedElementCount * componentsPerElement * componentByteSize ; + } else if( null != buffer ) { + return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ; + } else { + return 0; + } } @Override @@ -228,8 +292,9 @@ public class GLArrayDataWrapper implements GLArrayData { ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ - ", components "+components+ + ", components "+componentsPerElement+ ", stride "+strideB+"b "+strideL+"c"+ + ", mappedElementCount "+mappedElementCount+ ", buffer "+buffer+ ", vboEnabled "+vboEnabled+ ", vboName "+vboName+ @@ -299,12 +364,14 @@ public class GLArrayDataWrapper implements GLArrayData { this.vboTarget = vboTarget; } - protected void init(String name, int index, int components, int componentType, - boolean normalized, int stride, Buffer data, - boolean isVertexAttribute, - int vboName, long vboOffset, int vboUsage, int vboTarget) + protected void init(String name, int index, int componentsPerElement, int componentType, + boolean normalized, int stride, Buffer data, int mappedElementCount, + boolean isVertexAttribute, int vboName, long vboOffset, int vboUsage, int vboTarget) throws GLException { + if( 0<mappedElementCount && null != data ) { + throw new IllegalArgumentException("mappedElementCount:="+mappedElementCount+" specified, but passing non null buffer"); + } this.isVertexAttribute = isVertexAttribute; this.index = index; this.location = -1; @@ -333,19 +400,20 @@ public class GLArrayDataWrapper implements GLArrayData { if(0 > componentByteSize) { throw new GLException("Given componentType not supported: "+componentType+":\n\t"+this); } - if(0 >= components) { - throw new GLException("Invalid number of components: " + components); + if(0 >= componentsPerElement) { + throw new GLException("Invalid number of components: " + componentsPerElement); } - this.components = components; + this.componentsPerElement = componentsPerElement; - if(0<stride && stride<components*componentByteSize) { - throw new GLException("stride ("+stride+") lower than component bytes, "+components+" * "+componentByteSize); + if(0<stride && stride<componentsPerElement*componentByteSize) { + throw new GLException("stride ("+stride+") lower than component bytes, "+componentsPerElement+" * "+componentByteSize); } if(0<stride && stride%componentByteSize!=0) { throw new GLException("stride ("+stride+") not a multiple of bpc "+componentByteSize); } this.buffer = data; - this.strideB=(0==stride)?components*componentByteSize:stride; + this.mappedElementCount = mappedElementCount; + this.strideB=(0==stride)?componentsPerElement*componentByteSize:stride; this.strideL=strideB/componentByteSize; this.vboName= vboName; this.vboEnabled= 0 != vboName ; @@ -389,7 +457,7 @@ public class GLArrayDataWrapper implements GLArrayData { this.index = src.index; this.location = src.location; this.name = src.name; - this.components = src.components; + this.componentsPerElement = src.componentsPerElement; this.componentType = src.componentType; this.componentClazz = src.componentClazz; this.componentByteSize = src.componentByteSize; @@ -405,6 +473,7 @@ public class GLArrayDataWrapper implements GLArrayData { } else { this.buffer = null; } + this.mappedElementCount = src.mappedElementCount; this.isVertexAttribute = src.isVertexAttribute; this.vboOffset = src.vboOffset; this.vboName = src.vboName; @@ -417,14 +486,17 @@ public class GLArrayDataWrapper implements GLArrayData { protected int index; protected int location; protected String name; - protected int components; + protected int componentsPerElement; protected int componentType; protected Class<?> componentClazz; protected int componentByteSize; protected boolean normalized; - protected int strideB; // stride in bytes - protected int strideL; // stride in logical components + /** stride in bytes; strideB >= componentsPerElement * componentByteSize */ + protected int strideB; + /** stride in logical components */ + protected int strideL; protected Buffer buffer; + protected int mappedElementCount; protected boolean isVertexAttribute; protected long vboOffset; protected int vboName; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java index b11a6f931..cb225b96f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug658NEWT.java @@ -168,7 +168,7 @@ public class TestGLMesaBug658NEWT extends UITestCase { gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 32, null, GL.GL_STATIC_DRAW); Assert.assertTrue(gl.glGetError() == 0); - Assert.assertTrue(gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER) == name[0]); + Assert.assertTrue(gl.getBoundBuffer(GL.GL_ARRAY_BUFFER) == name[0]); gl.glEnableVertexAttribArray(1); Assert.assertTrue(gl.glGetError() == GL.GL_NO_ERROR); gl.glVertexAttribPointer(1, 4, GL.GL_FLOAT, false, 0, 0L); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java index 8fee7907a..ac82c74ea 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestMapBufferRead01NEWT.java @@ -37,6 +37,7 @@ import java.nio.ByteOrder; import javax.media.opengl.GL; import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLBufferStorage; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; @@ -46,13 +47,15 @@ import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; /** + * Verifies content of buffer storage's content + * as well as general buffer- and buffer-storage tracking. * * @author Luz, et.al. */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestMapBufferRead01NEWT extends UITestCase { static final boolean DEBUG = false; - + @Test public void testWriteRead01a() throws InterruptedException { if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { @@ -76,51 +79,64 @@ public class TestMapBufferRead01NEWT extends UITestCase { private void testWriteRead01(ByteBuffer verticiesBB) throws InterruptedException { final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOffscreenWindow( new GLCapabilities(GLProfile.getGL2GL3()), 800, 600, true); - final GL gl = winctx.context.getGL(); - - int[] vertexBuffer = new int[1]; - - verticiesBB.putFloat(0); - verticiesBB.putFloat(0.5f); - verticiesBB.putFloat(0); - - verticiesBB.putFloat(0.5f); - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(0); - - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(-0.5f); - verticiesBB.putFloat(0); - verticiesBB.rewind(); - if(DEBUG) { - for(int i=0; i < verticiesBB.capacity(); i+=4) { - System.out.println("java "+i+": "+verticiesBB.getFloat(i)); + try { + final GL gl = winctx.context.getGL(); + + int[] vertexBuffer = new int[1]; + + verticiesBB.putFloat(0); + verticiesBB.putFloat(0.5f); + verticiesBB.putFloat(0); + + verticiesBB.putFloat(0.5f); + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(0); + + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(-0.5f); + verticiesBB.putFloat(0); + verticiesBB.rewind(); + if(DEBUG) { + for(int i=0; i < verticiesBB.capacity(); i+=4) { + System.err.println("java "+i+": "+verticiesBB.getFloat(i)); + } } - } - gl.glGenBuffers(1, vertexBuffer, 0); + gl.glGenBuffers(1, vertexBuffer, 0); - gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffer[0]); - // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ); - gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW); - - ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY); - Assert.assertNotNull(bb); - - if(DEBUG) { + // gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_READ); + gl.glBufferData(GL.GL_ARRAY_BUFFER, verticiesBB.capacity(), verticiesBB, GL.GL_STATIC_DRAW); + + final int bufferName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); + final GLBufferStorage bufferStorage = gl.getBufferStorage(bufferName); + System.err.println("gpu-01 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage); + Assert.assertEquals("Buffer storage's bytes-buffer not null before map", null, bufferStorage.getMappedBuffer()); + + final ByteBuffer bb = gl.glMapBuffer(GL.GL_ARRAY_BUFFER, GL2GL3.GL_READ_ONLY); + Assert.assertNotNull(bb); + System.err.println("gpu-02 mapped GL_ARRAY_BUFFER -> "+bb); + System.err.println("gpu-03 GL_ARRAY_BUFFER -> bufferName "+bufferName+" -> "+bufferStorage); + Assert.assertEquals("Buffer storage size not equals buffer storage size", bufferStorage.getSize(), bb.capacity()); + Assert.assertEquals("Buffer storage's bytes-buffer not equal with mapped bytes-buffer", bufferStorage.getMappedBuffer(), bb); + + if(DEBUG) { + for(int i=0; i < bb.capacity(); i+=4) { + System.err.println("gpu "+i+": "+bb.getFloat(i)); + } + } for(int i=0; i < bb.capacity(); i+=4) { - System.out.println("gpu "+i+": "+bb.getFloat(i)); + Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0); } + gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER); + Assert.assertEquals("Buffer storage's bytes-buffer not null after unmap", null, bufferStorage.getMappedBuffer()); + } finally { + NEWTGLContext.destroyWindow(winctx); } - for(int i=0; i < bb.capacity(); i+=4) { - Assert.assertEquals(verticiesBB.getFloat(i), bb.getFloat(i), 0.0); - } - gl.glUnmapBuffer(GL.GL_ARRAY_BUFFER); - NEWTGLContext.destroyWindow(winctx); } public static void main(String args[]) throws IOException { String tstname = TestMapBufferRead01NEWT.class.getName(); org.junit.runner.JUnitCore.main(tstname); - } + } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java index a8c069f36..010368b4b 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT0.java @@ -100,13 +100,22 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { } @Test - public void testCommonAnimatorShared() throws InterruptedException { + public void test01CommonAnimatorSharedCopyBuffer() throws InterruptedException { + testCommonAnimatorSharedImpl(false); + } + @Test + public void test02CommonAnimatorMapBuffer() throws InterruptedException { + testCommonAnimatorSharedImpl(true); + } + private void testCommonAnimatorSharedImpl(boolean useMappedBuffers) throws InterruptedException { final Animator animator = new Animator(); // // 1st // final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); final GLWindow f1 = runTestGL(animator, 0, 0, g1, null); final GLContext ctx1 = f1.getContext(); Assert.assertTrue("Ctx is shared before shared creation", !ctx1.isShared()); @@ -178,30 +187,30 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { } catch(Exception e) { e.printStackTrace(); } - animator.stop(); - f1.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); + f3.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); { final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); - System.err.println("XXX-D-2.1:"); + System.err.println("XXX-D-0.1:"); MiscUtils.dumpSharedGLContext(ctx1); - System.err.println("XXX-D-2.2:"); + System.err.println("XXX-D-0.2:"); MiscUtils.dumpSharedGLContext(ctx2); - System.err.println("XXX-D-2.3:"); + System.err.println("XXX-D-0.3:"); MiscUtils.dumpSharedGLContext(ctx3); - Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); - Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); - Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); - Assert.assertEquals("Ctx1 has unexpected number of created shares", 2, ctx1Shares.size()); + Assert.assertTrue("Ctx1 is shared", ctx1.isShared()); + Assert.assertTrue("Ctx2 is shared", ctx2.isShared()); + Assert.assertTrue("Ctx3 is shared", ctx3.isShared()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size()); Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size()); - Assert.assertEquals("Ctx3 has unexpected number of created shares", 1, ctx3Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 2, ctx3Shares.size()); } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } f2.destroy(); Assert.assertTrue(AWTRobotUtil.waitForVisible(f2, false)); @@ -221,36 +230,42 @@ public class TestSharedContextVBOES2NEWT0 extends UITestCase { Assert.assertTrue("Ctx1 is not shared", ctx1.isShared()); Assert.assertTrue("Ctx2 is not shared", ctx2.isShared()); Assert.assertTrue("Ctx3 is not shared", ctx3.isShared()); - Assert.assertEquals("Ctx1 has unexpected number of created shares", 1, ctx1Shares.size()); + Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size()); Assert.assertEquals("Ctx2 has unexpected number of created shares", 1, ctx2Shares.size()); - Assert.assertEquals("Ctx3 has unexpected number of created shares", 0, ctx3Shares.size()); + Assert.assertEquals("Ctx3 has unexpected number of created shares", 1, ctx3Shares.size()); } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } - f3.destroy(); - Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); - Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f3, false)); + f1.destroy(); + Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); + Assert.assertTrue(AWTRobotUtil.waitForContextCreated(f1, false)); { final List<GLContext> ctx1Shares = ctx1.getCreatedShares(); final List<GLContext> ctx2Shares = ctx2.getCreatedShares(); final List<GLContext> ctx3Shares = ctx3.getCreatedShares(); - System.err.println("XXX-D-0.1:"); + System.err.println("XXX-D-2.1:"); MiscUtils.dumpSharedGLContext(ctx1); - System.err.println("XXX-D-0.2:"); + System.err.println("XXX-D-2.2:"); MiscUtils.dumpSharedGLContext(ctx2); - System.err.println("XXX-D-0.3:"); + System.err.println("XXX-D-2.3:"); MiscUtils.dumpSharedGLContext(ctx3); - Assert.assertTrue("Ctx1 is shared", !ctx1.isShared()); - Assert.assertTrue("Ctx2 is shared", !ctx2.isShared()); - Assert.assertTrue("Ctx3 is shared", !ctx3.isShared()); + Assert.assertTrue("Ctx1 is not shared", !ctx1.isShared()); + Assert.assertTrue("Ctx2 is not shared", !ctx2.isShared()); + Assert.assertTrue("Ctx3 is not shared", !ctx3.isShared()); Assert.assertEquals("Ctx1 has unexpected number of created shares", 0, ctx1Shares.size()); Assert.assertEquals("Ctx2 has unexpected number of created shares", 0, ctx2Shares.size()); Assert.assertEquals("Ctx3 has unexpected number of created shares", 0, ctx3Shares.size()); } + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); } static long duration = 1000; // ms + static long durationPostDestroy = 1000; // ms - ~60 frames post destroy public static void main(String args[]) { for(int i=0; i<args.length; i++) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java index c94ae1140..d06cc87a5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedContextVBOES2NEWT3.java @@ -92,19 +92,31 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { return glWindow; } + /** @Test - public void test01SyncedOneAnimatorCleanDtorOrder() throws InterruptedException { - syncedOneAnimator(true); + public void test01SyncedOneAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException { + syncedOneAnimator(true, false); + } + @Test + public void test02SyncedOneAnimatorCleanDtorOrderMapBuffer() throws InterruptedException { + syncedOneAnimator(true, true); } @Test - public void test02SyncedOneAnimatorDirtyDtorOrder() throws InterruptedException { - syncedOneAnimator(false); + public void test03SyncedOneAnimatorDirtyDtorOrderCopyBuffer() throws InterruptedException { + syncedOneAnimator(false, false); + } + @Test + public void test04SyncedOneAnimatorDirtyDtorOrderMapBuffer() throws InterruptedException { + syncedOneAnimator(false, true); } + */ - public void syncedOneAnimator(boolean destroyCleanOrder) throws InterruptedException { + public void syncedOneAnimator(boolean destroyCleanOrder, boolean useMappedBuffers) throws InterruptedException { final Animator animator = new Animator(); final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); final GLWindow f1 = createGLWindow(0, 0, g1); animator.add(f1); InsetsImmutable insets = f1.getInsets(); @@ -176,21 +188,29 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { } catch(Exception e) { e.printStackTrace(); } - // Stopped animator allows native windowing system 'repaint' event - // to trigger GLAD 'display' - animator.stop(); - Assert.assertEquals(false, animator.isAnimating()); if( destroyCleanOrder ) { System.err.println("XXX Destroy in clean order NOW"); f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } f2.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } f1.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } } else { System.err.println("XXX Destroy in creation order NOW - Driver Impl. Ma trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + animator.pause(); f1.destroy(); + animator.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + animator.pause(); f2.destroy(); + animator.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } } Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); @@ -198,21 +218,33 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { Assert.assertTrue(AWTRobotUtil.waitForRealized(f2, false)); Assert.assertTrue(AWTRobotUtil.waitForVisible(f3, false)); Assert.assertTrue(AWTRobotUtil.waitForRealized(f3, false)); + + animator.stop(); } @Test - public void test11ASyncEachAnimatorCleanDtorOrder() throws InterruptedException { - asyncEachAnimator(true); + public void test11ASyncEachAnimatorCleanDtorOrderCopyBuffer() throws InterruptedException { + asyncEachAnimator(true, false); + } + //@Test + public void test12ASyncEachAnimatorCleanDtorOrderMapBuffer() throws InterruptedException { + asyncEachAnimator(true, true); } - @Test - public void test12AsyncEachAnimatorDirtyDtorOrder() throws InterruptedException { - asyncEachAnimator(false); + //@Test + public void test13AsyncEachAnimatorDirtyDtorOrderCopyBuffers() throws InterruptedException { + asyncEachAnimator(false, false); + } + //@Test + public void test14AsyncEachAnimatorDirtyDtorOrderMapBuffers() throws InterruptedException { + asyncEachAnimator(false, true); } - public void asyncEachAnimator(boolean destroyCleanOrder) throws InterruptedException { + public void asyncEachAnimator(boolean destroyCleanOrder, boolean useMappedBuffers) throws InterruptedException { final Animator a1 = new Animator(); final GearsES2 g1 = new GearsES2(0); + g1.setUseMappedBuffers(useMappedBuffers); + g1.setValidateBuffers(true); final GLWindow f1 = createGLWindow(0, 0, g1); a1.add(f1); a1.start(); @@ -290,25 +322,37 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { } catch(Exception e) { e.printStackTrace(); } - // Stopped animator allows native windowing system 'repaint' event - // to trigger GLAD 'display' - a1.stop(); - Assert.assertEquals(false, a1.isAnimating()); - a2.stop(); - Assert.assertEquals(false, a2.isAnimating()); - a3.stop(); - Assert.assertEquals(false, a3.isAnimating()); if( destroyCleanOrder ) { System.err.println("XXX Destroy in clean order NOW"); + a3.stop(); f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + a2.stop(); f2.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + a1.stop(); f1.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } } else { System.err.println("XXX Destroy in creation order NOW - Driver Impl. May trigger driver Bug i.e. not postponing GL ctx destruction after releasing all refs."); + a1.stop(); + a2.pause(); + a3.pause(); f1.destroy(); + a2.resume(); + a3.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + a2.stop(); + a3.pause(); f2.destroy(); + a3.resume(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } + + a3.stop(); f3.destroy(); + try { Thread.sleep(durationPostDestroy); } catch(Exception e) { e.printStackTrace(); } } Assert.assertTrue(AWTRobotUtil.waitForVisible(f1, false)); Assert.assertTrue(AWTRobotUtil.waitForRealized(f1, false)); @@ -319,6 +363,7 @@ public class TestSharedContextVBOES2NEWT3 extends UITestCase { } static long duration = 1000; // ms + static long durationPostDestroy = 1000; // ms - ~60 frames post destroy public static void main(String args[]) { for(int i=0; i<args.length; i++) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java index 9526df2c7..00d360f6e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/GearsObject.java @@ -45,8 +45,9 @@ public abstract class GearsObject { public GLArrayDataServer outwardFace; public GLArrayDataServer insideRadiusCyl; public boolean isShared; + protected boolean validateBuffers = false; - public abstract GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage); + public abstract GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage); public abstract void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components); public abstract void draw(GL gl, float x, float y, float angle); @@ -61,16 +62,6 @@ public abstract class GearsObject { array.enableBuffer(gl, false); } - /** Init VBO and data .. */ - public final void init(GL gl) { - init(gl, frontFace); - init(gl, frontSide); - init(gl, backFace); - init(gl, backSide); - init(gl, outwardFace); - init(gl, insideRadiusCyl); - } - public void destroy(GL gl) { if(!isShared) { // could be already destroyed by shared configuration @@ -104,6 +95,7 @@ public abstract class GearsObject { public GearsObject ( GearsObject shared ) { isShared = true; + validateBuffers = shared.validateBuffers; frontFace = createInterleavedClone(shared.frontFace); addInterleavedVertexAndNormalArrays(frontFace, 3); backFace = createInterleavedClone(shared.backFace); @@ -120,12 +112,12 @@ public abstract class GearsObject { } public GearsObject ( + GL gl, + boolean useMappedBuffers, FloatBuffer gearColor, float inner_radius, float outer_radius, - float width, - int teeth, - float tooth_depth) + float width, int teeth, float tooth_depth, boolean validateBuffers) { final float dz = width * 0.5f; int i; @@ -137,6 +129,7 @@ public abstract class GearsObject { float normal[] = new float[3]; // final int tris_per_tooth = 32; + this.validateBuffers = validateBuffers; this.isShared = false; this.gearColor = gearColor; @@ -151,19 +144,28 @@ public abstract class GearsObject { final int vboUsage = GL.GL_STATIC_DRAW; - frontFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); + frontFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(frontFace, 3); - backFace = createInterleaved(6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); + backFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(backFace, 3); - frontSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, vboUsage); + frontSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage); addInterleavedVertexAndNormalArrays(frontSide, 3); - backSide = createInterleaved(6, GL.GL_FLOAT, false, 6*teeth, vboUsage); + backSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage); addInterleavedVertexAndNormalArrays(backSide, 3); - outwardFace = createInterleaved(6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage); + outwardFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(outwardFace, 3); - insideRadiusCyl = createInterleaved(6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage); + insideRadiusCyl = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage); addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3); + if( useMappedBuffers ) { + frontFace.mapStorage(gl, GL.GL_WRITE_ONLY); + backFace.mapStorage(gl, GL.GL_WRITE_ONLY); + frontSide.mapStorage(gl, GL.GL_WRITE_ONLY); + backSide.mapStorage(gl, GL.GL_WRITE_ONLY); + outwardFace.mapStorage(gl, GL.GL_WRITE_ONLY); + insideRadiusCyl.mapStorage(gl, GL.GL_WRITE_ONLY); + } + for (i = 0; i < teeth; i++) { angle = i * 2.0f * M_PI / teeth; sincos(angle + da * 0f, s, 0, c, 0); @@ -290,6 +292,23 @@ public abstract class GearsObject { vert(insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal); vert(insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal); insideRadiusCyl.seal(true); + + if( useMappedBuffers ) { + frontFace.unmapStorage(gl); + backFace.unmapStorage(gl); + frontSide.unmapStorage(gl); + backSide.unmapStorage(gl); + outwardFace.unmapStorage(gl); + insideRadiusCyl.unmapStorage(gl); + } else { + /** Init VBO and data .. */ + init(gl, frontFace); + init(gl, frontSide); + init(gl, backFace); + init(gl, backSide); + init(gl, outwardFace); + init(gl, insideRadiusCyl); + } } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java index 9f191d3b6..f4c5e8b2f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java @@ -63,6 +63,8 @@ public class GearsES1 implements GLEventListener { private GearsObject gear1=null, gear2=null, gear3=null; private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; private volatile boolean usesSharedGears = false; + private boolean useMappedBuffers = false; + private boolean validateBuffers = false; private float angle = 0.0f; private final int swapInterval; private final MouseListener gearsMouse = new GearsMouseAdapter(); @@ -115,6 +117,9 @@ public class GearsES1 implements GLEventListener { public boolean usesSharedGears() { return usesSharedGears; } + public void setUseMappedBuffers(boolean v) { useMappedBuffers = v; } + public void setValidateBuffers(boolean v) { validateBuffers = v; } + public void init(GLAutoDrawable drawable) { System.err.println(Thread.currentThread()+" GearsES1.init ..."); @@ -161,8 +166,7 @@ public class GearsES1 implements GLEventListener { /* make the gears */ if(null == gear1) { - gear1 = new GearsObjectES1(gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f); - gear1.init(gl); + gear1 = new GearsObjectES1(gl, useMappedBuffers, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, validateBuffers); System.err.println("gear1 created: "+gear1); } else { usesSharedGears = true; @@ -170,8 +174,7 @@ public class GearsES1 implements GLEventListener { } if(null == gear2) { - gear2 = new GearsObjectES1(gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f); - gear2.init(gl); + gear2 = new GearsObjectES1(gl, useMappedBuffers, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, validateBuffers); System.err.println("gear2 created: "+gear2); } else { usesSharedGears = true; @@ -179,8 +182,7 @@ public class GearsES1 implements GLEventListener { } if(null == gear3) { - gear3 = new GearsObjectES1(gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f); - gear3.init(gl); + gear3 = new GearsObjectES1(gl, useMappedBuffers, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, validateBuffers); System.err.println("gear3 created: "+gear3); } else { usesSharedGears = true; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java index fb9251e75..777fb04ae 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsObjectES1.java @@ -24,6 +24,8 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLException; import javax.media.opengl.fixedfunc.GLPointerFunc; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; @@ -35,14 +37,18 @@ import com.jogamp.opengl.util.GLArrayDataServer; */ public class GearsObjectES1 extends GearsObject { - public GearsObjectES1(FloatBuffer gearColor, float inner_radius, float outer_radius, float width, - int teeth, float tooth_depth) { - super(gearColor, inner_radius, outer_radius, width, teeth, tooth_depth); + public GearsObjectES1(GL gl, boolean useMappedBuffers, FloatBuffer gearColor, float inner_radius, + float outer_radius, float width, int teeth, float tooth_depth, boolean validateBuffers) { + super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers); } @Override - public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { - return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage); + public GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { + if( useMappedBuffers ) { + return GLArrayDataServer.createFixedInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage); + } else { + return GLArrayDataServer.createFixedInterleaved(comps, dataType, normalized, initialSize, vboUsage); + } } @Override @@ -54,6 +60,20 @@ public class GearsObjectES1 extends GearsObject { private void draw(GL2ES1 gl, GLArrayDataServer array, int mode) { if( !isShared || gl.glIsBuffer(array.getVBOName()) ) { array.enableBuffer(gl, true); + if( validateBuffers ) { + final int bufferTarget = array.getVBOTarget(); + final int bufferName = array.getVBOName(); + final long bufferSize = array.getSizeInBytes(); + final int hasBufferName = gl.getBoundBuffer(bufferTarget); + final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); + final boolean ok = bufferName == hasBufferName && + bufferName == hasStorage.getName() && + bufferSize == hasStorage.getSize(); + if( !ok ) { + throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+ + ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]"); + } + } gl.glDrawArrays(mode, 0, array.getElementCount()); array.enableBuffer(gl, false); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index d85d38618..653937a7e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -67,6 +67,8 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL private float panX = 0.0f, panY = 0.0f, panZ=0.0f; private volatile GearsObjectES2 gear1=null, gear2=null, gear3=null; private GearsES2 sharedGears = null; + private boolean useMappedBuffers = false; + private boolean validateBuffers = false; private volatile boolean usesSharedGears = false; private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; private float angle = 0.0f; @@ -164,6 +166,9 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL public boolean usesSharedGears() { return usesSharedGears; } + public void setUseMappedBuffers(boolean v) { useMappedBuffers = v; } + public void setValidateBuffers(boolean v) { validateBuffers = v; } + private static final int TIME_OUT = 2000; // 2s private static final int POLL_DIVIDER = 20; // TO/20 private static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ; @@ -184,14 +189,14 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL @Override public void init(GLAutoDrawable drawable) { if(null != sharedGears && !sharedGears.isInit() ) { - System.err.println(Thread.currentThread()+" GearsES2.init "+sid()+": pending shared Gears .. re-init later XXXXX"); + System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": pending shared Gears .. re-init later XXXXX"); drawable.setGLEventListenerInitState(this, false); return; } final GL2ES2 gl = drawable.getGL().getGL2ES2(); if(verbose) { - System.err.println(Thread.currentThread()+" GearsES2.init "+sid()+": tileRendererInUse "+tileRendererInUse); + System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": tileRendererInUse "+tileRendererInUse+", "+this); System.err.println("GearsES2 init "+sid()+" on "+Thread.currentThread()); System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); System.err.println("INIT GL IS: " + gl.getClass().getName()); @@ -245,8 +250,7 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL } } else { if(null == gear1) { - gear1 = new GearsObjectES2(st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - gear1.init(gl); + gear1 = new GearsObjectES2(gl, useMappedBuffers, st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); if(verbose) { System.err.println("gear1 "+sid()+" created: "+gear1); } @@ -260,8 +264,7 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL } if(null == gear2) { - gear2 = new GearsObjectES2(st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - gear2.init(gl); + gear2 = new GearsObjectES2(gl, useMappedBuffers, st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); if(verbose) { System.err.println("gear2 "+sid()+" created: "+gear2); } @@ -275,8 +278,7 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL } if(null == gear3) { - gear3 = new GearsObjectES2(st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU); - gear3.init(gl); + gear3 = new GearsObjectES2(gl, useMappedBuffers, st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers); if(verbose) { System.err.println("gear3 "+sid()+" created: "+gear2); } @@ -310,7 +312,7 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL isInit = true; if(verbose) { - System.err.println(Thread.currentThread()+" GearsES2.init "+sid()+" FIN "+this); + System.err.println(Thread.currentThread()+" GearsES2.init.X "+sid()+" FIN "+this); } } @@ -516,7 +518,7 @@ public class GearsES2 implements GLEventListener, TileRendererBase.TileRendererL @Override public String toString() { - return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+"]"; + return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+", sharedGears "+sharedGears+"]"; } boolean confinedFixedCenter = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java index f3367ad1c..4cef6394e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsObjectES2.java @@ -24,6 +24,8 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; @@ -41,13 +43,13 @@ public class GearsObjectES2 extends GearsObject { final GLUniformData colorUniform; final ShaderState st; - public GearsObjectES2(ShaderState st, FloatBuffer gearColor, float inner_radius, float outer_radius, - float width, int teeth, - float tooth_depth, - PMVMatrix pmvMatrix, - GLUniformData pmvMatrixUniform, GLUniformData colorUniform) + public GearsObjectES2(GL gl, boolean useMappedBuffers, ShaderState st, FloatBuffer gearColor, + float inner_radius, float outer_radius, + float width, + int teeth, + float tooth_depth, PMVMatrix pmvMatrix, GLUniformData pmvMatrixUniform, GLUniformData colorUniform, boolean validateBuffers) { - super(gearColor, inner_radius, outer_radius, width, teeth, tooth_depth); + super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers); this.pmvMatrix = pmvMatrix; this.pmvMatrixUniform = pmvMatrixUniform; this.colorUniform = colorUniform; @@ -78,8 +80,12 @@ public class GearsObjectES2 extends GearsObject { } @Override - public GLArrayDataServer createInterleaved(int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { - return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage); + public GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage) { + if( useMappedBuffers ) { + return GLArrayDataServer.createGLSLInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage); + } else { + return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage); + } } @Override @@ -90,6 +96,21 @@ public class GearsObjectES2 extends GearsObject { private void draw(GL2ES2 gl, GLArrayDataServer array, int mode, int face) { if( !isShared || gl.glIsBuffer(array.getVBOName()) ) { + if( validateBuffers ) { + array.bindBuffer(gl, true); + final int bufferTarget = array.getVBOTarget(); + final int bufferName = array.getVBOName(); + final long bufferSize = array.getSizeInBytes(); + final int hasBufferName = gl.getBoundBuffer(bufferTarget); + final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName); + final boolean ok = bufferName == hasBufferName && + bufferName == hasStorage.getName() && + bufferSize == hasStorage.getSize(); + if( !ok ) { + throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+ + ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]"); + } + } array.enableBuffer(gl, true); // System.err.println("XXX Draw face "+face+" of "+this); gl.glDrawArrays(mode, 0, array.getElementCount()); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java new file mode 100644 index 000000000..f0c9fc6ed --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareMappedES2.java @@ -0,0 +1,281 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.TileRendererBase; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLBufferStorage; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; + +public class RedSquareMappedES2 implements GLEventListener, TileRendererBase.TileRendererListener { + private ShaderState st; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer vertices ; + private GLArrayDataServer colors ; + private long t0; + private int swapInterval = 0; + private float aspect = 1.0f; + private boolean doRotate = true; + private boolean clearBuffers = true; + private TileRendererBase tileRendererInUse = null; + private boolean doRotateBeforePrinting; + + public RedSquareMappedES2(int swapInterval) { + this.swapInterval = swapInterval; + } + + public RedSquareMappedES2() { + this.swapInterval = 1; + } + + @Override + public void addTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = tr; + doRotateBeforePrinting = doRotate; + setDoRotation(false); + } + @Override + public void removeTileRendererNotify(TileRendererBase tr) { + tileRendererInUse = null; + setDoRotation(doRotateBeforePrinting); + } + @Override + public void startTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.startTileRendering: "+tr); + } + @Override + public void endTileRendering(TileRendererBase tr) { + System.err.println("RedSquareES2.endTileRendering: "+tr); + } + + public void setAspect(float aspect) { this.aspect = aspect; } + public void setDoRotation(boolean rotate) { this.doRotate = rotate; } + public void setClearBuffers(boolean v) { clearBuffers = v; } + + @Override + public void init(GLAutoDrawable glad) { + System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + + System.err.println("RedSquareES2 init on "+Thread.currentThread()); + System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities()); + System.err.println("INIT GL IS: " + gl.getClass().getName()); + System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); + if( !gl.hasGLSL() ) { + System.err.println("No GLSL available, no rendering."); + return; + } + st = new ShaderState(); + st.setVerbose(true); + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", + "shader/bin", "RedSquareShader", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", + "shader/bin", "RedSquareShader", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + // Allocate Vertex Array + vertices = GLArrayDataServer.createGLSLMapped("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + { + final GLArrayDataServer ad = vertices; + final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY); + { + final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer(); + fb.put(-2); fb.put( 2); fb.put( 0); + fb.put( 2); fb.put( 2); fb.put( 0); + fb.put(-2); fb.put(-2); fb.put( 0); + fb.put( 2); fb.put(-2); fb.put( 0); + } + ad.unmapStorage(gl); + } + vertices.seal(gl, true); + st.ownAttribute(vertices, true); + vertices.enableBuffer(gl, false); + + // Allocate Color Array + colors = GLArrayDataServer.createGLSLMapped("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + { + final GLArrayDataServer ad = colors; + final GLBufferStorage store = ad.mapStorage(gl, GL.GL_WRITE_ONLY); + { + final FloatBuffer fb = store.getMappedBuffer().asFloatBuffer(); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + fb.put(0); fb.put(0); fb.put(1); fb.put(1); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + fb.put(1); fb.put(0); fb.put(0); fb.put(1); + } + ad.unmapStorage(gl); + } + colors.seal(gl, true); + st.ownAttribute(colors, true); + colors.enableBuffer(gl, false); + + // OpenGL Render Settings + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + st.useProgram(gl, false); + + t0 = System.currentTimeMillis(); + System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); + } + + @Override + public void display(GLAutoDrawable glad) { + long t1 = System.currentTimeMillis(); + + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( clearBuffers ) { + if( null != tileRendererInUse ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + } else { + gl.glClearColor(0, 0, 0, 0); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + if( !gl.hasGLSL() ) { + return; + } + st.useProgram(gl, true); + // One rotation every four seconds + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, -10); + if(doRotate) { + float ang = ((t1 - t0) * 360.0F) / 4000.0F; + pmvMatrix.glRotatef(ang, 0, 0, 1); + pmvMatrix.glRotatef(ang, 0, 1, 0); + } + st.uniform(gl, pmvMatrixUniform); + + // Draw a square + vertices.enableBuffer(gl, true); + colors.enableBuffer(gl, true); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + vertices.enableBuffer(gl, false); + colors.enableBuffer(gl, false); + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); + } + reshapeImpl(gl, x, y, width, height, width, height); + } + + @Override + public void reshapeTile(TileRendererBase tr, + int tileX, int tileY, int tileWidth, int tileHeight, + int imageWidth, int imageHeight) { + final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2(); + gl.setSwapInterval(0); + reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight); + } + + void reshapeImpl(GL2ES2 gl, int tileX, int tileY, int tileWidth, int tileHeight, int imageWidth, int imageHeight) { + System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse); + // Thread.dumpStack(); + if( !gl.hasGLSL() ) { + return; + } + + st.useProgram(gl, true); + // Set location in front of camera + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + + // compute projection parameters 'normal' perspective + final float fovy=45f; + final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect; + final float zNear=1f; + final float zFar=100f; + + // compute projection parameters 'normal' frustum + final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + final float bottom=-1.0f*top; + final float left=aspect2*bottom; + final float right=aspect2*top; + final float w = right - left; + final float h = top - bottom; + + // compute projection parameters 'tiled' + final float l = left + tileX * w / imageWidth; + final float r = l + tileWidth * w / imageWidth; + final float b = bottom + tileY * h / imageHeight; + final float t = b + tileHeight * h / imageHeight; + + pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar); + //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN"); + } + + @Override + public void dispose(GLAutoDrawable glad) { + System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse); + final GL2ES2 gl = glad.getGL().getGL2ES2(); + if( !gl.hasGLSL() ) { + return; + } + st.destroy(gl); + st = null; + pmvMatrix.destroy(); + pmvMatrix = null; + System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN"); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index bfed497e8..5d5b0c9a1 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -102,6 +102,7 @@ public class TestGearsES2NEWT extends UITestCase { static boolean mainRun = false; static boolean exclusiveContext = false; static boolean useAnimator = true; + static boolean useMappedBuffers = false; static enum SysExit { none, testExit, testError, testEDTError, displayExit, displayError, displayEDTError }; static SysExit sysExit = SysExit.none; @@ -135,6 +136,8 @@ public class TestGearsES2NEWT extends UITestCase { final GearsES2 demo = new GearsES2(swapInterval); demo.setPMVUseBackingArray(pmvUseBackingArray); + demo.setUseMappedBuffers(useMappedBuffers); + demo.setValidateBuffers(true); glWindow.addGLEventListener(demo); final SnapshotGLEventListener snap = new SnapshotGLEventListener(); @@ -549,6 +552,8 @@ public class TestGearsES2NEWT extends UITestCase { forceGL3 = true; } else if(args[i].equals("-gl2")) { forceGL2 = true; + } else if(args[i].equals("-mappedBuffers")) { + useMappedBuffers = true; } else if(args[i].equals("-wait")) { waitForKey = true; } else if(args[i].equals("-mouseInvisible")) { @@ -623,6 +628,7 @@ public class TestGearsES2NEWT extends UITestCase { System.err.println("exclusiveContext "+exclusiveContext); System.err.println("useAnimator "+useAnimator); System.err.println("sysExitWithin "+sysExit); + System.err.println("mappedBuffers "+useMappedBuffers); if(waitForKey) { UITestCase.waitForKey("Start"); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java index 69879ddb2..6300bbd68 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,12 +20,12 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ - + package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; import com.jogamp.newt.event.KeyAdapter; @@ -35,13 +35,13 @@ import com.jogamp.opengl.test.junit.util.AWTRobotUtil; import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.UITestCase; import com.jogamp.opengl.test.junit.util.QuitAdapter; - import com.jogamp.opengl.util.Animator; - import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareMappedES2; import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import org.junit.Assert; @@ -61,6 +61,7 @@ public class TestRedSquareES2NEWT extends UITestCase { static boolean forceGL3 = false; static boolean mainRun = false; static boolean doRotate = true; + static boolean useMappedBuffers = false; @BeforeClass public static void initClass() { @@ -79,14 +80,22 @@ public class TestRedSquareES2NEWT extends UITestCase { glWindow.setTitle(getSimpleTestName(".")); glWindow.setSize(width, height); - final RedSquareES2 demo = new RedSquareES2(vsync ? 1 : -1); - demo.setDoRotation(doRotate); + final GLEventListener demo; + if( useMappedBuffers ) { + final RedSquareMappedES2 red = new RedSquareMappedES2(vsync ? 1 : -1); + red.setDoRotation(doRotate); + demo = red; + } else { + final RedSquareES2 red = new RedSquareES2(vsync ? 1 : -1); + red.setDoRotation(doRotate); + demo = red; + } glWindow.addGLEventListener(demo); final SnapshotGLEventListener snap = new SnapshotGLEventListener(); snap.setPostSNDetail(demo.getClass().getSimpleName()); glWindow.addGLEventListener(snap); - + Animator animator = new Animator(glWindow); QuitAdapter quitAdapter = new QuitAdapter(); @@ -99,7 +108,7 @@ public class TestRedSquareES2NEWT extends UITestCase { public void keyReleased(KeyEvent e) { if( !e.isPrintableKey() || e.isAutoRepeat() ) { return; - } + } if(e.getKeyChar()=='f') { new Thread() { public void run() { @@ -115,16 +124,16 @@ public class TestRedSquareES2NEWT extends UITestCase { }); animator.start(); - + glWindow.setVisible(true); System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); - + animator.setUpdateFPSFrames(60, System.err); snap.setMakeSnapshot(); - + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { Thread.sleep(100); } @@ -157,11 +166,11 @@ public class TestRedSquareES2NEWT extends UITestCase { } } } - + @Test public void test02GL3() throws InterruptedException { if(mainRun) return; - + if( !GLProfile.isAvailable(GLProfile.GL3) ) { System.err.println("GL3 n/a"); return; @@ -169,7 +178,7 @@ public class TestRedSquareES2NEWT extends UITestCase { final GLProfile glp = GLProfile.get(GLProfile.GL3); final GLCapabilities caps = new GLCapabilities( glp ); runTestGL(caps); - } + } static long duration = 500; // ms @@ -185,6 +194,8 @@ public class TestRedSquareES2NEWT extends UITestCase { forceGL3 = true; } else if(args[i].equals("-norotate")) { doRotate = false; + } else if(args[i].equals("-mappedBuffers")) { + useMappedBuffers = true; } else if(args[i].equals("-loops")) { i++; loops = MiscUtils.atoi(args[i], 1); @@ -196,6 +207,7 @@ public class TestRedSquareES2NEWT extends UITestCase { System.err.println("loop shutdown "+loop_shutdown); System.err.println("forceES2 "+forceES2); System.err.println("forceGL3 "+forceGL3); + System.err.println("mappedBuffers "+useMappedBuffers); org.junit.runner.JUnitCore.main(TestRedSquareES2NEWT.class.getName()); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java index 361c2916a..f55e331a7 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/glsl/GLSLMiscHelper.java @@ -145,7 +145,7 @@ public class GLSLMiscHelper { Assert.assertTrue(vDataArray.sealed()); Assert.assertEquals(4, vDataArray.getElementCount()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP + Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP validateGLArrayDataServerState(gl, st, vDataArray); return vDataArray; } @@ -190,7 +190,7 @@ public class GLSLMiscHelper { Assert.assertTrue(cDataArray.isVBOWritten()); Assert.assertTrue(cDataArray.sealed()); Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - Assert.assertEquals(0, gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP + Assert.assertEquals(0, gl.getBoundBuffer(GL.GL_ARRAY_BUFFER)); // should be cleared ASAP validateGLArrayDataServerState(gl, st, cDataArray); return cDataArray; } |