1 /** 2 * Copyright 2010 JogAmp Community. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without modification, are 5 * permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, this list of 8 * conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 * of conditions and the following disclaimer in the documentation and/or other materials 12 * provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * The views and conclusions contained in the software and documentation are those of the 25 * authors and should not be interpreted as representing official policies, either expressed 26 * or implied, of JogAmp Community. 27 */ 28 29 package com.jogamp.opengl.util; 30 31 import java.nio.Buffer; 32 import java.nio.ByteBuffer; 33 import java.nio.FloatBuffer; 34 import java.nio.IntBuffer; 35 import java.nio.ShortBuffer; 36 37 import com.jogamp.opengl.GL; 38 import com.jogamp.opengl.GL2ES2; 39 import com.jogamp.opengl.GLArrayData; 40 import com.jogamp.opengl.GLBufferStorage; 41 import com.jogamp.opengl.GLException; 42 import com.jogamp.opengl.fixedfunc.GLPointerFuncUtil; 43 44 import com.jogamp.common.nio.Buffers; 45 46 import jogamp.opengl.util.GLArrayHandler; 47 import jogamp.opengl.util.GLArrayHandlerInterleaved; 48 import jogamp.opengl.util.GLDataArrayHandler; 49 import jogamp.opengl.util.GLFixedArrayHandler; 50 import jogamp.opengl.util.GLFixedArrayHandlerFlat; 51 import jogamp.opengl.util.glsl.GLSLArrayHandler; 52 import jogamp.opengl.util.glsl.GLSLArrayHandlerFlat; 53 import jogamp.opengl.util.glsl.GLSLArrayHandlerInterleaved; 54 55 56 public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataEditable { 57 58 // 59 // lifetime matters 60 // 61 62 /** 63 * Create a VBO, using a predefined fixed function array index 64 * and starting with a given Buffer object incl it's stride 65 * 66 * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. 67 * On profile ES2 the fixed function emulation will transform these calls to 68 * EnableVertexAttribArray and VertexAttribPointer calls, 69 * and a predefined vertex attribute variable name will be chosen. 70 * 71 * The default name mapping will be used, 72 * see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}. 73 * 74 * @param index The GL array index 75 * @param compsPerElement component count per element 76 * @param dataType The component's OpenGL data type 77 * @param normalized Whether the data shall be normalized 78 * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes 79 * @param buffer the user define data 80 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 81 * 82 * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int) 83 */ createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, final int vboUsage)84 public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int stride, 85 final Buffer buffer, final int vboUsage) 86 throws GLException 87 { 88 final GLArrayDataServer ads = new GLArrayDataServer(); 89 final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); 90 ads.init(null, index, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, 91 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); 92 return ads; 93 } 94 95 /** 96 * Create a VBO, using a predefined fixed function array index 97 * and starting with a new created Buffer object with initialElementCount size 98 * 99 * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. 100 * On profile ES2 the fixed function emulation will transform these calls to 101 * EnableVertexAttribArray and VertexAttribPointer calls, 102 * and a predefined vertex attribute variable name will be chosen. 103 * 104 * The default name mapping will be used, 105 * see {@link GLPointerFuncUtil#getPredefinedArrayIndexName(int)}. 106 * 107 * @param index The GL array index 108 * @param compsPerElement component count per element 109 * @param dataType The component's OpenGL data type 110 * @param normalized Whether the data shall be normalized 111 * @param initialElementCount 112 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 113 * 114 * @see com.jogamp.opengl.GLContext#getPredefinedArrayIndexName(int) 115 */ createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)116 public static GLArrayDataServer createFixed(final int index, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, 117 final int vboUsage) 118 throws GLException 119 { 120 final GLArrayDataServer ads = new GLArrayDataServer(); 121 final GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); 122 ads.init(null, index, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, 123 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); 124 return ads; 125 } 126 127 /** 128 * Create a VBO, using a custom GLSL array attribute name 129 * and starting with a new created Buffer object with initialElementCount size 130 * @param name The custom name for the GL attribute 131 * @param compsPerElement component count per element 132 * @param dataType The component's OpenGL data type 133 * @param normalized Whether the data shall be normalized 134 * @param initialElementCount 135 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 136 */ createGLSL(final String name, final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)137 public static GLArrayDataServer createGLSL(final String name, final int compsPerElement, 138 final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage) 139 throws GLException 140 { 141 final GLArrayDataServer ads = new GLArrayDataServer(); 142 final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); 143 ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount, 144 0 /* mappedElementCount */, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 145 return ads; 146 } 147 148 /** 149 * Create a VBO, using a custom GLSL array attribute name 150 * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. 151 * @param name The custom name for the GL attribute 152 * @param compsPerElement component count per element 153 * @param dataType The component's OpenGL data type 154 * @param normalized Whether the data shall be normalized 155 * @param mappedElementCount 156 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 157 */ createGLSLMapped(final String name, final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage)158 public static GLArrayDataServer createGLSLMapped(final String name, final int compsPerElement, 159 final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage) 160 throws GLException 161 { 162 final GLArrayDataServer ads = new GLArrayDataServer(); 163 final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); 164 ads.init(name, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */, 165 mappedElementCount, true, glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 166 ads.seal(true); 167 return ads; 168 } 169 170 /** 171 * Create a VBO, using a custom GLSL array attribute name 172 * and starting with a given Buffer object incl it's stride 173 * @param name The custom name for the GL attribute 174 * @param compsPerElement component count per element 175 * @param dataType The component's OpenGL data type 176 * @param normalized Whether the data shall be normalized 177 * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes 178 * @param buffer the user define data 179 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 180 */ createGLSL(final String name, final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, final int vboUsage)181 public static GLArrayDataServer createGLSL(final String name, final int compsPerElement, 182 final int dataType, final boolean normalized, final int stride, final Buffer buffer, 183 final int vboUsage) 184 throws GLException 185 { 186 final GLArrayDataServer ads = new GLArrayDataServer(); 187 final GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); 188 ads.init(name, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, true, 189 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 190 return ads; 191 } 192 193 /** 194 * Create a VBO data object for any target w/o render pipeline association, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}. 195 * 196 * Hence no index, name for a fixed function pipeline nor vertex attribute is given. 197 * 198 * @param compsPerElement component count per element 199 * @param dataType The component's OpenGL data type 200 * @param stride in bytes from one element to the other. If zero, compsPerElement * compSizeInBytes 201 * @param buffer the user define data 202 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 203 * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. 204 * {@link GL#glGenBuffers(int, int[], int) 205 */ createData(final int compsPerElement, final int dataType, final int stride, final Buffer buffer, final int vboUsage, final int vboTarget)206 public static GLArrayDataServer createData(final int compsPerElement, final int dataType, final int stride, 207 final Buffer buffer, final int vboUsage, final int vboTarget) 208 throws GLException 209 { 210 final GLArrayDataServer ads = new GLArrayDataServer(); 211 final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); 212 ads.init(null, -1, compsPerElement, dataType, false, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, 213 glArrayHandler, 0, 0, vboUsage, vboTarget, false); 214 return ads; 215 } 216 217 /** 218 * Create a VBO data object for any target w/o render pipeline association, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}. 219 * 220 * Hence no index, name for a fixed function pipeline nor vertex attribute is given. 221 * 222 * @param compsPerElement component count per element 223 * @param dataType The component's OpenGL data type 224 * @param initialElementCount 225 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 226 * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. 227 */ createData(final int compsPerElement, final int dataType, final int initialElementCount, final int vboUsage, final int vboTarget)228 public static GLArrayDataServer createData(final int compsPerElement, final int dataType, final int initialElementCount, 229 final int vboUsage, final int vboTarget) 230 throws GLException 231 { 232 final GLArrayDataServer ads = new GLArrayDataServer(); 233 final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); 234 ads.init(null, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false, 235 glArrayHandler, 0, 0, vboUsage, vboTarget, false); 236 return ads; 237 } 238 239 /** 240 * Create a VBO data object for any target w/o render pipeline association, i.e. {@link GL#GL_ELEMENT_ARRAY_BUFFER}, 241 * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. 242 * <p> 243 * No index, name for a fixed function pipeline nor vertex attribute is given. 244 * </p> 245 * 246 * @param compsPerElement component count per element 247 * @param dataType The component's OpenGL data type 248 * @param initialElementCount 249 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 250 * @param vboTarget {@link GL#GL_ELEMENT_ARRAY_BUFFER}, .. 251 */ createDataMapped(final int compsPerElement, final int dataType, final int mappedElementCount, final int vboUsage, final int vboTarget)252 public static GLArrayDataServer createDataMapped(final int compsPerElement, final int dataType, final int mappedElementCount, 253 final int vboUsage, final int vboTarget) 254 throws GLException 255 { 256 final GLArrayDataServer ads = new GLArrayDataServer(); 257 final GLArrayHandler glArrayHandler = new GLDataArrayHandler(ads); 258 ads.init(null, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false, 259 glArrayHandler, 0, 0, vboUsage, vboTarget, false); 260 return ads; 261 } 262 263 /** 264 * Create a VBO for fixed function interleaved array data 265 * starting with a new created Buffer object with initialElementCount size. 266 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> 267 * 268 * @param compsPerElement The total number of all interleaved components per element. 269 * @param dataType The component's OpenGL data type 270 * @param normalized Whether the data shall be normalized 271 * @param initialElementCount The initial number of all interleaved elements 272 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 273 */ createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)274 public static GLArrayDataServer createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, 275 final int vboUsage) 276 throws GLException 277 { 278 final GLArrayDataServer ads = new GLArrayDataServer(); 279 final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); 280 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, initialElementCount, 0 /* mappedElementCount */, false, 281 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); 282 return ads; 283 } 284 285 /** 286 * Create a VBO for fixed function interleaved array data 287 * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. 288 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> 289 * 290 * @param compsPerElement The total number of all interleaved components per element. 291 * @param dataType The component's OpenGL data type 292 * @param normalized Whether the data shall be normalized 293 * @param mappedElementCount The total number of all interleaved elements 294 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 295 */ createFixedInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage)296 public static GLArrayDataServer createFixedInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, 297 final int vboUsage) 298 throws GLException 299 { 300 final GLArrayDataServer ads = new GLArrayDataServer(); 301 final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); 302 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, false, 0, null, 0 /* initialElementCount */, mappedElementCount, false, 303 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); 304 ads.seal(true); 305 return ads; 306 } 307 308 /** 309 * Create a VBO for fixed function interleaved array data 310 * starting with a given Buffer object incl it's stride 311 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addFixedSubArray(int, int, int)}.</p> 312 * 313 * @param compsPerElement The total number of all interleaved components per element. 314 * @param dataType The component's OpenGL data type 315 * @param normalized Whether the data shall be normalized 316 * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes 317 * @param buffer The user define data of all interleaved elements 318 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 319 */ createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, final int vboUsage)320 public static GLArrayDataServer createFixedInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, 321 final int vboUsage) 322 throws GLException 323 { 324 final GLArrayDataServer ads = new GLArrayDataServer(); 325 final GLArrayHandler glArrayHandler = new GLArrayHandlerInterleaved(ads); 326 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, 327 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, false); 328 return ads; 329 } 330 331 /** 332 * Configure a segment of this fixed function interleaved array (see {@link #createFixedInterleaved(int, int, boolean, int, int)}). 333 * <p> 334 * This method may be called several times as long the sum of interleaved components does not 335 * exceed the total component count of the created interleaved array.</p> 336 * <p> 337 * The memory of the the interleaved array is being used.</p> 338 * <p> 339 * Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p> 340 * 341 * @param index The GL array index, maybe -1 if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} 342 * @param comps This interleaved array segment's component count per element 343 * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} 344 */ addFixedSubArray(final int index, final int comps, final int vboTarget)345 public GLArrayData addFixedSubArray(final int index, final int comps, final int vboTarget) { 346 if(interleavedOffset >= getComponentCount() * getComponentSizeInBytes()) { 347 final int iOffC = interleavedOffset / getComponentSizeInBytes(); 348 throw new GLException("Interleaved offset > total components ("+iOffC+" > "+getComponentCount()+")"); 349 } 350 if(usesGLSL) { 351 throw new GLException("buffer uses GLSL"); 352 } 353 final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride(); 354 final GLArrayDataWrapper ad; 355 if( 0 < mappedElementCount ) { 356 ad = GLArrayDataWrapper.createFixed( 357 index, comps, getComponentType(), 358 getNormalized(), subStrideB, mappedElementCount, 359 getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); 360 } else { 361 ad = GLArrayDataWrapper.createFixed( 362 index, comps, getComponentType(), 363 getNormalized(), subStrideB, getBuffer(), 364 getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); 365 } 366 ad.setVBOEnabled(isVBO()); 367 interleavedOffset += comps * getComponentSizeInBytes(); 368 if(GL.GL_ARRAY_BUFFER == vboTarget) { 369 glArrayHandler.addSubHandler(new GLFixedArrayHandlerFlat(ad)); 370 } 371 return ad; 372 } 373 374 /** 375 * Create a VBO for GLSL interleaved array data 376 * starting with a new created Buffer object with initialElementCount size. 377 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> 378 * 379 * @param compsPerElement The total number of all interleaved components per element. 380 * @param dataType The component's OpenGL data type 381 * @param normalized Whether the data shall be normalized 382 * @param initialElementCount The initial number of all interleaved elements 383 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 384 */ createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, final int vboUsage)385 public static GLArrayDataServer createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int initialElementCount, 386 final int vboUsage) 387 throws GLException 388 { 389 final GLArrayDataServer ads = new GLArrayDataServer(); 390 final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); 391 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, initialElementCount, 0 /* mappedElementCount */, false, 392 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 393 return ads; 394 } 395 396 /** 397 * Create a VBO for GLSL interleaved array data 398 * intended for GPU buffer storage mapping, see {@link GLBufferStorage}, via {@link #mapStorage(GL, int)} and {@link #mapStorage(GL, long, long, int)}. 399 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> 400 * 401 * @param compsPerElement The total number of all interleaved components per element. 402 * @param dataType The component's OpenGL data type 403 * @param normalized Whether the data shall be normalized 404 * @param mappedElementCount The total number of all interleaved elements 405 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 406 */ createGLSLInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage)407 public static GLArrayDataServer createGLSLInterleavedMapped(final int compsPerElement, final int dataType, final boolean normalized, final int mappedElementCount, final int vboUsage) 408 throws GLException 409 { 410 final GLArrayDataServer ads = new GLArrayDataServer(); 411 final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); 412 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, 0, null, 0 /* initialElementCount */, mappedElementCount, false, 413 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 414 ads.seal(true); 415 return ads; 416 } 417 418 /** 419 * Create a VBO for GLSL interleaved array data 420 * starting with a given Buffer object incl it's stride 421 * <p>User needs to <i>configure</i> the interleaved segments via {@link #addGLSLSubArray(int, int, int)}.</p> 422 * 423 * @param compsPerElement The total number of all interleaved components per element. 424 * @param dataType The component's OpenGL data type 425 * @param normalized Whether the data shall be normalized 426 * @param stride in bytes from one element of a sub-array to the other. If zero, compsPerElement * compSizeInBytes 427 * @param buffer The user define data of all interleaved elements 428 * @param vboUsage {@link GL2ES2#GL_STREAM_DRAW}, {@link GL#GL_STATIC_DRAW} or {@link GL#GL_DYNAMIC_DRAW} 429 */ createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, final int vboUsage)430 public static GLArrayDataServer createGLSLInterleaved(final int compsPerElement, final int dataType, final boolean normalized, final int stride, final Buffer buffer, 431 final int vboUsage) 432 throws GLException 433 { 434 final GLArrayDataServer ads = new GLArrayDataServer(); 435 final GLArrayHandler glArrayHandler = new GLSLArrayHandlerInterleaved(ads); 436 ads.init(GLPointerFuncUtil.mgl_InterleaveArray, -1, compsPerElement, dataType, normalized, stride, buffer, buffer.limit(), 0 /* mappedElementCount */, false, 437 glArrayHandler, 0, 0, vboUsage, GL.GL_ARRAY_BUFFER, true); 438 return ads; 439 } 440 441 /** 442 * Configure a segment of this GLSL interleaved array (see {@link #createGLSLInterleaved(int, int, boolean, int, int)}). 443 * <p> 444 * This method may be called several times as long the sum of interleaved components does not 445 * exceed the total component count of the created interleaved array.</p> 446 * <p> 447 * The memory of the the interleaved array is being used.</p> 448 * <p> 449 * Must be called before using the array, eg: {@link #seal(boolean)}, {@link #putf(float)}, .. </p> 450 * @param name The custom name for the GL attribute, maybe null if vboTarget is {@link GL#GL_ELEMENT_ARRAY_BUFFER} 451 * @param comps This interleaved array segment's component count per element 452 * @param vboTarget {@link GL#GL_ARRAY_BUFFER} or {@link GL#GL_ELEMENT_ARRAY_BUFFER} 453 */ addGLSLSubArray(final String name, final int comps, final int vboTarget)454 public GLArrayData addGLSLSubArray(final String name, final int comps, final int vboTarget) { 455 if(interleavedOffset >= getComponentCount() * getComponentSizeInBytes()) { 456 final int iOffC = interleavedOffset / getComponentSizeInBytes(); 457 throw new GLException("Interleaved offset > total components ("+iOffC+" > "+getComponentCount()+")"); 458 } 459 if(!usesGLSL) { 460 throw new GLException("buffer uses fixed function"); 461 } 462 final int subStrideB = ( 0 == getStride() ) ? getComponentCount() * getComponentSizeInBytes() : getStride(); 463 final GLArrayDataWrapper ad; 464 if( 0 < mappedElementCount ) { 465 ad = GLArrayDataWrapper.createGLSL( 466 name, comps, getComponentType(), 467 getNormalized(), subStrideB, mappedElementCount, 468 getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); 469 } else { 470 ad = GLArrayDataWrapper.createGLSL( 471 name, comps, getComponentType(), 472 getNormalized(), subStrideB, getBuffer(), 473 getVBOName(), interleavedOffset, getVBOUsage(), vboTarget); 474 } 475 ad.setVBOEnabled(isVBO()); 476 interleavedOffset += comps * getComponentSizeInBytes(); 477 if(GL.GL_ARRAY_BUFFER == vboTarget) { 478 glArrayHandler.addSubHandler(new GLSLArrayHandlerFlat(ad)); 479 } 480 return ad; 481 } 482 setInterleavedOffset(final int interleavedOffset)483 public final void setInterleavedOffset(final int interleavedOffset) { 484 this.interleavedOffset = interleavedOffset; 485 } 486 getInterleavedOffset()487 public final int getInterleavedOffset() { 488 return interleavedOffset; 489 } 490 491 // 492 // Data matters GLArrayData 493 // 494 495 // 496 // Data and GL state modification .. 497 // 498 499 @Override destroy(final GL gl)500 public void destroy(final GL gl) { 501 // super.destroy(gl): 502 // - GLArrayDataClient.destroy(gl): disables & clears client-side buffer 503 // - GLArrayDataWrapper.destroy(gl) (clears all values 'vboName' ..) 504 final int _vboName = vboName; 505 super.destroy(gl); 506 if(_vboName!=0) { 507 final int[] tmp = new int[] { _vboName } ; 508 gl.glDeleteBuffers(1, tmp, 0); 509 vboName = 0; 510 } 511 } 512 513 // 514 // data matters 515 // 516 517 /** 518 * Convenient way do disable the VBO behavior and 519 * switch to client side data one 520 * Only possible if buffer is defined. 521 */ 522 @Override setVBOEnabled(final boolean vboUsage)523 public void setVBOEnabled(final boolean vboUsage) { 524 checkSeal(false); 525 super.setVBOEnabled(vboUsage); 526 } 527 mapStorage(final GL gl, final int access)528 public GLBufferStorage mapStorage(final GL gl, final int access) { 529 if( null != this.getBuffer() ) { 530 throw new IllegalStateException("user buffer not null"); 531 } 532 if( null != mappedStorage ) { 533 throw new IllegalStateException("already mapped: "+mappedStorage); 534 } 535 checkSeal(true); 536 bindBuffer(gl, true); 537 gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); 538 final GLBufferStorage storage = gl.mapBuffer(getVBOTarget(), access); 539 setMappedBuffer(storage); 540 bindBuffer(gl, false); 541 seal(false); 542 rewind(); 543 return storage; 544 } mapStorage(final GL gl, final long offset, final long length, final int access)545 public GLBufferStorage mapStorage(final GL gl, final long offset, final long length, final int access) { 546 if( null != this.getBuffer() ) { 547 throw new IllegalStateException("user buffer not null"); 548 } 549 if( null != mappedStorage ) { 550 throw new IllegalStateException("already mapped: "+mappedStorage); 551 } 552 checkSeal(true); 553 bindBuffer(gl, true); 554 gl.glBufferData(getVBOTarget(), getSizeInBytes(), null, getVBOUsage()); 555 final GLBufferStorage storage = gl.mapBufferRange(getVBOTarget(), offset, length, access); 556 setMappedBuffer(storage); 557 bindBuffer(gl, false); 558 seal(false); 559 rewind(); 560 return storage; 561 } setMappedBuffer(final GLBufferStorage storage)562 private final void setMappedBuffer(final GLBufferStorage storage) { 563 mappedStorage = storage; 564 final ByteBuffer bb = storage.getMappedBuffer(); 565 if(componentClazz==ByteBuffer.class) { 566 buffer = bb; 567 } else if(componentClazz==ShortBuffer.class) { 568 buffer = bb.asShortBuffer(); 569 } else if(componentClazz==IntBuffer.class) { 570 buffer = bb.asIntBuffer(); 571 } else if(componentClazz==FloatBuffer.class) { 572 buffer = bb.asFloatBuffer(); 573 } else { 574 throw new GLException("Given Buffer Class not supported: "+componentClazz+":\n\t"+this); 575 } 576 } 577 unmapStorage(final GL gl)578 public void unmapStorage(final GL gl) { 579 if( null == mappedStorage ) { 580 throw new IllegalStateException("not mapped"); 581 } 582 mappedStorage = null; 583 buffer = null; 584 seal(true); 585 bindBuffer(gl, true); 586 gl.glUnmapBuffer(getVBOTarget()); 587 bindBuffer(gl, false); 588 } 589 590 @Override toString()591 public String toString() { 592 return "GLArrayDataServer["+name+ 593 ", index "+index+ 594 ", location "+location+ 595 ", isVertexAttribute "+isVertexAttribute+ 596 ", usesGLSL "+usesGLSL+ 597 ", usesShaderState "+(null!=shaderState)+ 598 ", dataType 0x"+Integer.toHexString(componentType)+ 599 ", bufferClazz "+componentClazz+ 600 ", elements "+getElementCount()+ 601 ", components "+componentsPerElement+ 602 ", stride "+strideB+"b "+strideL+"c"+ 603 ", initialElementCount "+initialElementCount+ 604 ", mappedElementCount "+mappedElementCount+ 605 ", mappedStorage "+mappedStorage+ 606 ", vboEnabled "+vboEnabled+ 607 ", vboName "+vboName+ 608 ", vboUsage 0x"+Integer.toHexString(vboUsage)+ 609 ", vboTarget 0x"+Integer.toHexString(vboTarget)+ 610 ", vboOffset "+vboOffset+ 611 ", sealed "+sealed+ 612 ", bufferEnabled "+bufferEnabled+ 613 ", bufferWritten "+bufferWritten+ 614 ", buffer "+buffer+ 615 ", alive "+alive+ 616 "]"; 617 } 618 619 // 620 // non public matters .. 621 // 622 623 @Override init(final String name, final int index, final int comps, final int dataType, final boolean normalized, final int stride, final Buffer data, final int initialElementCount, final int mappedElementCount, final boolean isVertexAttribute, final GLArrayHandler glArrayHandler, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget, final boolean usesGLSL)624 protected void init(final String name, final int index, final int comps, final int dataType, final boolean normalized, 625 final int stride, final Buffer data, final int initialElementCount, final int mappedElementCount, 626 final boolean isVertexAttribute, 627 final GLArrayHandler glArrayHandler, final int vboName, final long vboOffset, final int vboUsage, final int vboTarget, final boolean usesGLSL) 628 throws GLException 629 { 630 super.init(name, index, comps, dataType, normalized, stride, data, initialElementCount, mappedElementCount, isVertexAttribute, 631 glArrayHandler, vboName, vboOffset, vboUsage, vboTarget, usesGLSL); 632 633 vboEnabled=true; 634 } 635 636 @Override init_vbo(final GL gl)637 protected void init_vbo(final GL gl) { 638 super.init_vbo(gl); 639 if(vboEnabled && vboName==0) { 640 final int[] tmp = new int[1]; 641 gl.glGenBuffers(1, tmp, 0); 642 vboName = tmp[0]; 643 if(0 < interleavedOffset) { 644 glArrayHandler.setSubArrayVBOName(vboName); 645 } 646 } 647 } 648 GLArrayDataServer()649 protected GLArrayDataServer() { } 650 651 /** 652 * Copy Constructor 653 * <p> 654 * Buffer is {@link Buffers#slice(Buffer) sliced}, i.e. sharing content but using own state. 655 * </p> 656 * <p> 657 * All other values are simply copied. 658 * </p> 659 */ GLArrayDataServer(final GLArrayDataServer src)660 public GLArrayDataServer(final GLArrayDataServer src) { 661 super(src); 662 this.interleavedOffset = src.interleavedOffset; 663 this.mappedStorage = src.mappedStorage; 664 } 665 666 private int interleavedOffset = 0; 667 private GLBufferStorage mappedStorage = null; 668 } 669 670