diff options
author | Sven Gothel <[email protected]> | 2014-01-21 18:16:22 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-01-21 18:16:22 +0100 |
commit | 09fc7aa5539731bb0fba835caee61f6eb837ecff (patch) | |
tree | 12798cf9a888d24b10e3aee8f677755a84f06a17 | |
parent | 19c91de9f02fc713fce09277ea243d966cbc9ac8 (diff) |
Bug 942: GLBufferObjectTracker: Tracking GLBufferStorage accurately, synchronized and secure [1/2]
GLBufferSizeTracker becomes GLBufferObjectTracker
and tracks the buffer's data store, GLBufferStorage, accurately, synchronized and secure.
Synchronization is required, since the GLBufferStorage can be
shared across many GLContext on multiple threads.
This requires all GLBufferStorage lifecycle affecting GL functions
to utilize synchronized GLBufferObjectTracker methods
while passing a native GL-func callback.
These GL functions are:
- glBufferData, glBufferStorage (GL 4.4), glNamedBufferDataEXT
Creating the GLBufferStorage object
- glMapBuffer, glMapBufferRange, and their *Named*EXT variants
- glUnmapBuffer, glUnmapNamedBufferEXT
'glDeleteBuffers' can simply notify the GLBufferObjectTracker
No more HashMap is required to associate the mapped buffer address
to the mapped ByteBuffer.
GLBufferObjectTracker simply utilizes a
buffer-name (int) -> GLBufferStorage
map.
+++
The security aspect shall be implemented by validating all arguments
whether they match the required GL constraints,
as well as validating tracked states like 'size'.
The following functions will throw an GLException accordingly:
- glBufferData, glNamedBufferDataEXT
* @throws GLException if size is less-than zero
* @throws GLException if a native GL-Error occurs
- glBufferStorage (GL 4.4)
* @throws GLException if size is less-or-eqaul zero
* @throws GLException if a native GL-Error occurs
- glMapBuffer, and it's *Named*EXT variant
* @throws GLException if buffer is not bound to target
* @throws GLException if buffer is not tracked
* @throws GLException if buffer is already mapped
* @throws GLException if buffer has invalid store size, i.e. less-than zero
- glMapBufferRange, and it's *Named*EXT variant
* @throws GLException if buffer is not bound to target
* @throws GLException if buffer is not tracked
* @throws GLException if buffer is already mapped
* @throws GLException if buffer has invalid store size, i.e. less-than zero
* @throws GLException if buffer mapping range does not fit, incl. offset
- glMapBufferRange, and it's *Named*EXT variant
Only clear mapped buffer reference of GLBufferStorage
if native unmap was successful.
Further more special error handling shall be applied to:
- glMapBuffer, and it's *Named*EXT variant,
glMapBuffer, and it's *Named*EXT variant
- A zero GLBufferStorage size will avoid a native call and
returns null
- A null native mapping result indicating an error will
not cause a GLException but returns null
This allows the user to handle this case.
22 files changed, 1539 insertions, 483 deletions
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg index e9996c64b..74ead0498 100644 --- a/make/config/jogl/gl-common.cfg +++ b/make/config/jogl/gl-common.cfg @@ -56,12 +56,66 @@ Ignore glDebugMessageCallbackARB Ignore glDebugMessageCallbackKHR Ignore glDebugMessageCallback -# Manually implement glMapBuffer and glMapBufferRange as the size of the returned buffer -# can only be computed by calling another routine +# +# Manually implement following GL functions to be redirected +# to GLBufferObjectTracker. +# +ManuallyImplement glBufferData +ForceProcAddressGen glBufferData +MethodJavadoc glBufferData * <p> +MethodJavadoc glBufferData * Throws a {@link GLException} if GL-function constraints are not met or the native GL-function fails. +MethodJavadoc glBufferData * </p> +MethodJavadoc glBufferData * <p> +MethodJavadoc glBufferData * @throws GLException if buffer is not bound to target +MethodJavadoc glBufferData * @throws GLException if size is less-than zero +MethodJavadoc glBufferData * @throws GLException if a native GL-Error occurs +MethodJavadoc glBufferData * </p> + +# FIXME: Add for OpenGL 4.4 +#Ignore glBufferStorage +#ManuallyImplement glBufferStorage +#ForceProcAddressGen glBufferStorage +#MethodJavadoc glBufferStorage * <p> +#MethodJavadoc glBufferStorage * Throws a {@link GLException} if GL-function constraints are not met or the native GL-function fails. +#MethodJavadoc glBufferStorage * </p> +#MethodJavadoc glBufferStorage * <p> +#MethodJavadoc glBufferStorage * @throws GLException if buffer is not bound to target +#MethodJavadoc glBufferStorage * @throws GLException if size is less-or-equal zero +#MethodJavadoc glBufferStorage * @throws GLException if a native GL-Error occurs +#MethodJavadoc glBufferStorage * </p> + ManuallyImplement glMapBuffer ForceProcAddressGen glMapBuffer +MethodJavadoc glMapBuffer * <p> +MethodJavadoc glMapBuffer * Throws a {@link GLException} if GL-function constraints are not met. +MethodJavadoc glMapBuffer * </p> +MethodJavadoc glMapBuffer * <p> +MethodJavadoc glMapBuffer * Returns {@link GL#mapBuffer(int, int)}'s {@link GLBufferStorage#getMappedBuffer()}. +MethodJavadoc glMapBuffer * </p> +MethodJavadoc glMapBuffer * @throws GLException if buffer is not bound to target +MethodJavadoc glMapBuffer * @throws GLException if buffer is not tracked +MethodJavadoc glMapBuffer * @throws GLException if buffer is already mapped +MethodJavadoc glMapBuffer * @throws GLException if buffer has invalid store size, i.e. less-than zero +MethodJavadoc glMapBuffer * </p> + ManuallyImplement glMapBufferRange ForceProcAddressGen glMapBufferRange +MethodJavadoc glMapBufferRange * <p> +MethodJavadoc glMapBufferRange * Throws a {@link GLException} if GL-function constraints are not met. +MethodJavadoc glMapBufferRange * </p> +MethodJavadoc glMapBufferRange * <p> +MethodJavadoc glMapBufferRange * Returns {@link GL#mapBufferRange(int, long, long, int)}'s {@link GLBufferStorage#getMappedBuffer()}. +MethodJavadoc glMapBufferRange * </p> +MethodJavadoc glMapBufferRange * <p> +MethodJavadoc glMapBufferRange * @throws GLException if buffer is not bound to target +MethodJavadoc glMapBufferRange * @throws GLException if buffer is not tracked +MethodJavadoc glMapBufferRange * @throws GLException if buffer is already mapped +MethodJavadoc glMapBufferRange * @throws GLException if buffer has invalid store size, i.e. less-than zero +MethodJavadoc glMapBufferRange * @throws GLException if buffer mapping range does not fit, incl. offset +MethodJavadoc glMapBufferRange * </p> + +ManuallyImplement glUnmapBuffer +ForceProcAddressGen glUnmapBuffer # Ignore the ATI_map_object_buffer extension for now unless someone # claims they need it, as it will undoubtedly require a similar @@ -550,15 +604,18 @@ JavaEpilogue glBindFramebuffer _context.setBoundFramebuffer(target, framebuffer # JavaPrologue glBegin inBeginEndPair = true; JavaEpilogue glEnd inBeginEndPair = false; -JavaEpilogue glBindBuffer bufferStateTracker.setBoundBufferObject({0}, {1}); -JavaEpilogue glBindBufferARB bufferStateTracker.setBoundBufferObject({0}, {1}); -JavaEpilogue glBindVertexArray bufferStateTracker.setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, {0}); -JavaEpilogue glPushClientAttrib bufferStateTracker.clearBufferObjectState(); -JavaEpilogue glPushClientAttrib glStateTracker.pushAttrib(mask); -JavaEpilogue glPopClientAttrib bufferStateTracker.clearBufferObjectState(); -JavaEpilogue glPopClientAttrib glStateTracker.popAttrib(); -JavaPrologue glBufferData synchronized(bufferSizeTracker) { -JavaEpilogue glBufferData bufferSizeTracker.setBufferSize(bufferStateTracker, {0}, this, {1}); } + +JavaEpilogue glBindBuffer bufferStateTracker.setBoundBufferObject({0}, {1}); +JavaEpilogue glBindBufferARB bufferStateTracker.setBoundBufferObject({0}, {1}); +JavaEpilogue glBindBufferBase bufferStateTracker.setBoundBufferObject({0}, {2}); +JavaEpilogue glBindBufferRange bufferStateTracker.setBoundBufferObject({0}, {2}); +JavaEpilogue glBindVertexArray bufferStateTracker.setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, {0}); +JavaEpilogue glPushClientAttrib bufferStateTracker.clear(); +JavaEpilogue glPushClientAttrib glStateTracker.pushAttrib(mask); +JavaEpilogue glPopClientAttrib bufferStateTracker.clear(); +JavaEpilogue glPopClientAttrib glStateTracker.popAttrib(); + +JavaPrologue glDeleteBuffers bufferObjectTracker.notifyBuffersDeleted({0}, {1}); BufferObjectKind Array glColorPointer BufferObjectKind Array glEdgeFlagPointer diff --git a/make/config/jogl/gl-gl4bc.cfg b/make/config/jogl/gl-gl4bc.cfg index 48ecb7378..6ccbace44 100644 --- a/make/config/jogl/gl-gl4bc.cfg +++ b/make/config/jogl/gl-gl4bc.cfg @@ -55,12 +55,51 @@ Include gl3-desktop.cfg Include gl3-common.cfg Include gl2_es2-CustomJavaCode.cfg -# Manually implement glMapNamedBufferEXT as the size of the returned buffer -# can only be computed by calling another routine +# +# Manually implement following GL functions to be redirected +# to GLBufferObjectTracker. +# +ManuallyImplement glNamedBufferDataEXT +ForceProcAddressGen glNamedBufferDataEXT +MethodJavadoc glNamedBufferDataEXT * <p> +MethodJavadoc glNamedBufferDataEXT * Throws a {@link GLException} if GL-function constraints are not met or the native GL-function fails. +MethodJavadoc glNamedBufferDataEXT * </p> +MethodJavadoc glNamedBufferDataEXT * <p> +MethodJavadoc glNamedBufferDataEXT * @throws GLException if size is less-than zero +MethodJavadoc glNamedBufferDataEXT * @throws GLException if a native GL-Error occurs +MethodJavadoc glNamedBufferDataEXT * </p> + ManuallyImplement glMapNamedBufferEXT ForceProcAddressGen glMapNamedBufferEXT -JavaPrologue glNamedBufferDataEXT synchronized(bufferSizeTracker) { -JavaEpilogue glNamedBufferDataEXT bufferSizeTracker.setDirectStateBufferSize({0}, this, {1}); } +MethodJavadoc glMapNamedBufferEXT * <p> +MethodJavadoc glMapNamedBufferEXT * Throws a {@link GLException} if GL-function constraints are not met. +MethodJavadoc glMapNamedBufferEXT * </p> +MethodJavadoc glMapNamedBufferEXT * <p> +MethodJavadoc glMapNamedBufferEXT * Returns {@link GL2#mapNamedBuffer(int, int)}'s {@link GLBufferStorage#getMappedBuffer()}. +MethodJavadoc glMapNamedBufferEXT * </p> +MethodJavadoc glMapNamedBufferEXT * <p> +MethodJavadoc glMapNamedBufferEXT * @throws GLException if buffer is not tracked +MethodJavadoc glMapNamedBufferEXT * @throws GLException if buffer is already mapped +MethodJavadoc glMapNamedBufferEXT * @throws GLException if buffer has invalid store size, i.e. less-than zero +MethodJavadoc glMapNamedBufferEXT * </p> + +ManuallyImplement glMapNamedBufferRangeEXT +ForceProcAddressGen glMapNamedBufferRangeEXT +MethodJavadoc glMapNamedBufferRangeEXT * <p> +MethodJavadoc glMapNamedBufferRangeEXT * Throws a {@link GLException} if GL-function constraints are not met. +MethodJavadoc glMapNamedBufferRangeEXT * </p> +MethodJavadoc glMapNamedBufferRangeEXT * <p> +MethodJavadoc glMapNamedBufferRangeEXT * Returns {@link GL2#mapNamedBufferRange(int, long, long, int)}'s {@link GLBufferStorage#getMappedBuffer()}. +MethodJavadoc glMapNamedBufferRangeEXT * </p> +MethodJavadoc glMapNamedBufferRangeEXT * <p> +MethodJavadoc glMapNamedBufferRangeEXT * @throws GLException if buffer is not tracked +MethodJavadoc glMapNamedBufferRangeEXT * @throws GLException if buffer is already mapped +MethodJavadoc glMapNamedBufferRangeEXT * @throws GLException if buffer has invalid store size, i.e. less-than zero +MethodJavadoc glMapNamedBufferRangeEXT * @throws GLException if buffer mapping range does not fit, incl. offset +MethodJavadoc glMapNamedBufferRangeEXT * </p> + +ManuallyImplement glUnmapNamedBufferEXT +ForceProcAddressGen glUnmapNamedBufferEXT # Manuall implement glDebugMessageCallback* using the proc address resolver ForceProcAddressGen glDebugMessageCallback diff --git a/make/config/jogl/gl-if-CustomJavaCode-es3.java b/make/config/jogl/gl-if-CustomJavaCode-es3.java index b68b5123a..3f976d514 100644 --- a/make/config/jogl/gl-if-CustomJavaCode-es3.java +++ b/make/config/jogl/gl-if-CustomJavaCode-es3.java @@ -8,7 +8,11 @@ public static final long GL_TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFFL ; /** Part of <code>GL_ARB_shader_image_load_store</code> */ public static final int GL_ALL_BARRIER_BITS = 0xFFFFFFFF ; +/** @deprecated Avoid original GL API namespace conflict. Use {@link #isPBOPackBound()} */ public boolean glIsPBOPackBound(); +public boolean isPBOPackBound(); +/** @deprecated Avoid original GL API namespace conflict. Use {@link #isPBOUnpackBound()} */ public boolean glIsPBOUnpackBound(); +public boolean isPBOUnpackBound(); diff --git a/make/config/jogl/gl-if-gl2.cfg b/make/config/jogl/gl-if-gl2.cfg index 37f7b6feb..0120bd674 100644 --- a/make/config/jogl/gl-if-gl2.cfg +++ b/make/config/jogl/gl-if-gl2.cfg @@ -26,6 +26,7 @@ Include gl-desktop.cfg Include gl-if-gl3-ignores.cfg Include gl-if-gl4-ignores.cfg +IncludeAs CustomJavaCode GL2 gl-if-CustomJavaCode-gl2.java IncludeAs CustomJavaCode GL2 gl-if-CustomJavaCode-gl_compat.java IncludeAs CustomJavaCode GL2 gl2_es2-common-cpubufferJavaCode.java IncludeAs CustomJavaCode GL2 gl2-common-cpubufferJavaCode.java diff --git a/make/config/jogl/gl-impl-CustomCCode-gl4bc.c b/make/config/jogl/gl-impl-CustomCCode-gl4bc.c index 4ddc27bf2..42e5700ab 100644 --- a/make/config/jogl/gl-impl-CustomCCode-gl4bc.c +++ b/make/config/jogl/gl-impl-CustomCCode-gl4bc.c @@ -1,6 +1,77 @@ /* Java->C glue code: * Java package: jogamp.opengl.gl4.GL4bcImpl - * Java method: long dispatch_glMapBuffer(int target, int access) + * Java method: void dispatch_glBufferData(int target, long size, java.nio.Buffer data, int usage) + * C function: void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + */ +JNIEXPORT void JNICALL +Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glBufferData(JNIEnv *env, jobject _unused, jint target, jlong size, jobject data, jint data_byte_offset, jboolean data_is_nio, jint usage, jlong procAddress) { + typedef void (APIENTRY*_local_PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + _local_PFNGLBUFFERDATAPROC ptr_glBufferData; + GLvoid * _data_ptr = NULL; + if ( NULL != data ) { + _data_ptr = (GLvoid *) ( JNI_TRUE == data_is_nio ? (*env)->GetDirectBufferAddress(env, data) : (*env)->GetPrimitiveArrayCritical(env, data, NULL) ); } + ptr_glBufferData = (_local_PFNGLBUFFERDATAPROC) (intptr_t) procAddress; + assert(ptr_glBufferData != NULL); + (* ptr_glBufferData) ((GLenum) target, (GLsizeiptr) size, (GLvoid *) (((char *) _data_ptr) + data_byte_offset), (GLenum) usage); + if ( JNI_FALSE == data_is_nio && NULL != data ) { + (*env)->ReleasePrimitiveArrayCritical(env, data, _data_ptr, JNI_ABORT); } +} + +/** FIXME Add for OpenGL 4.4: glBufferStorage */ + +/* Java->C glue code: + * Java package: jogamp.opengl.gl4.GL4bcImpl + * Java method: void dispatch_glNamedBufferDataEXT(int buffer, long size, java.nio.Buffer data, int usage) + * C function: void glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage); + */ +JNIEXPORT void JNICALL +Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glNamedBufferDataEXT(JNIEnv *env, jobject _unused, jint buffer, jlong size, jobject data, jint data_byte_offset, jboolean data_is_nio, jint usage, jlong procAddress) { + typedef void (APIENTRY*_local_PFNGLNAMEDBUFFERDATAEXTPROC)(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage); + _local_PFNGLNAMEDBUFFERDATAEXTPROC ptr_glNamedBufferDataEXT; + GLvoid * _data_ptr = NULL; + if ( NULL != data ) { + _data_ptr = (GLvoid *) ( JNI_TRUE == data_is_nio ? (*env)->GetDirectBufferAddress(env, data) : (*env)->GetPrimitiveArrayCritical(env, data, NULL) ); } + ptr_glNamedBufferDataEXT = (_local_PFNGLNAMEDBUFFERDATAEXTPROC) (intptr_t) procAddress; + assert(ptr_glNamedBufferDataEXT != NULL); + (* ptr_glNamedBufferDataEXT) ((GLuint) buffer, (GLsizeiptr) size, (GLvoid *) (((char *) _data_ptr) + data_byte_offset), (GLenum) usage); + if ( JNI_FALSE == data_is_nio && NULL != data ) { + (*env)->ReleasePrimitiveArrayCritical(env, data, _data_ptr, JNI_ABORT); } +} + +/* Java->C glue code: + * Java package: jogamp.opengl.gl4.GL4bcImpl + * Java method: boolean dispatch_glUnmapBuffer(int target) + * C function: GLboolean glUnmapBuffer(GLenum target); + */ +JNIEXPORT jboolean JNICALL +Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glUnmapBuffer(JNIEnv *env, jobject _unused, jint target, jlong procAddress) { + typedef GLboolean (APIENTRY*_local_PFNGLUNMAPBUFFERPROC)(GLenum target); + _local_PFNGLUNMAPBUFFERPROC ptr_glUnmapBuffer; + GLboolean _res; + ptr_glUnmapBuffer = (_local_PFNGLUNMAPBUFFERPROC) (intptr_t) procAddress; + assert(ptr_glUnmapBuffer != NULL); + _res = (* ptr_glUnmapBuffer) ((GLenum) target); + return _res; +} + +/* Java->C glue code: + * Java package: jogamp.opengl.gl4.GL4bcImpl + * Java method: boolean dispatch_glUnmapNamedBufferEXT(int buffer) + * C function: GLboolean glUnmapNamedBufferEXT(GLuint buffer); + */ +JNIEXPORT jboolean JNICALL +Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glUnmapNamedBufferEXT(JNIEnv *env, jobject _unused, jint buffer, jlong procAddress) { + typedef GLboolean (APIENTRY*_local_PFNGLUNMAPNAMEDBUFFEREXTPROC)(GLuint buffer); + _local_PFNGLUNMAPNAMEDBUFFEREXTPROC ptr_glUnmapNamedBufferEXT; + GLboolean _res; + ptr_glUnmapNamedBufferEXT = (_local_PFNGLUNMAPNAMEDBUFFEREXTPROC) (intptr_t) procAddress; + assert(ptr_glUnmapNamedBufferEXT != NULL); + _res = (* ptr_glUnmapNamedBufferEXT) ((GLuint) buffer); + return _res; +} + +/* Java->C glue code: + * Java package: jogamp.opengl.gl4.GL4bcImpl * Java method: long dispatch_glMapBuffer(int target, int access) * C function: void * glMapBuffer(GLenum target, GLenum access); */ JNIEXPORT jlong JNICALL @@ -40,10 +111,26 @@ Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glMapNamedBufferEXT(JNIEnv *env, jobj void * _res; ptr_glMapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC) (intptr_t) glProcAddress; assert(ptr_glMapNamedBufferEXT != NULL); - _res = (* ptr_glMapNamedBufferEXT) ((GLenum) target, (GLenum) access); + _res = (* ptr_glMapNamedBufferEXT) ((GLuint) target, (GLenum) access); + return (jlong) (intptr_t) _res; +} + +/* Java->C glue code: + * Java package: jogamp.opengl.gl4.GL4bcImpl + * Java method: java.nio.ByteBuffer dispatch_glMapNamedBufferRangeEXT(int buffer, long offset, long length, int access) + * C function: void * glMapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); + */ +JNIEXPORT jlong JNICALL +Java_jogamp_opengl_gl4_GL4bcImpl_dispatch_1glMapNamedBufferRangeEXT(JNIEnv *env, jobject _unused, jint buffer, jlong offset, jlong length, jint access, jlong procAddress) { + PFNGLMAPNAMEDBUFFERRANGEEXTPROC ptr_glMapNamedBufferRangeEXT; + void * _res; + ptr_glMapNamedBufferRangeEXT = (PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (intptr_t) procAddress; + assert(ptr_glMapNamedBufferRangeEXT != NULL); + _res = (* ptr_glMapNamedBufferRangeEXT) ((GLuint) buffer, (GLintptr) offset, (GLsizeiptr) length, (GLbitfield) access); return (jlong) (intptr_t) _res; } + /* Java->C glue code: * Java package: jogamp.opengl.gl4.GL4bcImpl * Java method: ByteBuffer newDirectByteBuffer(long addr, long capacity); diff --git a/make/config/jogl/gl-impl-CustomCCode-gles1.c b/make/config/jogl/gl-impl-CustomCCode-gles1.c index 88cfe4418..83b8c7586 100644 --- a/make/config/jogl/gl-impl-CustomCCode-gles1.c +++ b/make/config/jogl/gl-impl-CustomCCode-gles1.c @@ -1,3 +1,38 @@ +/* Java->C glue code: + * Java package: jogamp.opengl.es1.GLES1Impl + * Java method: void dispatch_glBufferData(int target, long size, java.nio.Buffer data, int usage) + * C function: void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + */ +JNIEXPORT void JNICALL +Java_jogamp_opengl_es1_GLES1Impl_dispatch_1glBufferData(JNIEnv *env, jobject _unused, jint target, jlong size, jobject data, jint data_byte_offset, jboolean data_is_nio, jint usage, jlong procAddress) { + typedef void (GL_APIENTRY*_local_PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + _local_PFNGLBUFFERDATAPROC ptr_glBufferData; + GLvoid * _data_ptr = NULL; + if ( NULL != data ) { + _data_ptr = (GLvoid *) ( JNI_TRUE == data_is_nio ? (*env)->GetDirectBufferAddress(env, data) : (*env)->GetPrimitiveArrayCritical(env, data, NULL) ); } + ptr_glBufferData = (_local_PFNGLBUFFERDATAPROC) (intptr_t) procAddress; + assert(ptr_glBufferData != NULL); + (* ptr_glBufferData) ((GLenum) target, (GLsizeiptr) size, (GLvoid *) (((char *) _data_ptr) + data_byte_offset), (GLenum) usage); + if ( JNI_FALSE == data_is_nio && NULL != data ) { + (*env)->ReleasePrimitiveArrayCritical(env, data, _data_ptr, JNI_ABORT); } +} + +/* Java->C glue code: + * Java package: jogamp.opengl.es1.GLES1Impl + * Java method: boolean dispatch_glUnmapBuffer(int target) + * C function: GLboolean glUnmapBufferOES(GLenum target); + */ +JNIEXPORT jboolean JNICALL +Java_jogamp_opengl_es1_GLES1Impl_dispatch_1glUnmapBuffer(JNIEnv *env, jobject _unused, jint target, jlong procAddress) { + typedef GLboolean (GL_APIENTRY*_local_PFNGLUNMAPBUFFEROESPROC)(GLenum target); + _local_PFNGLUNMAPBUFFEROESPROC ptr_glUnmapBufferOES; + GLboolean _res; + ptr_glUnmapBufferOES = (_local_PFNGLUNMAPBUFFEROESPROC) (intptr_t) procAddress; + assert(ptr_glUnmapBufferOES != NULL); + _res = (* ptr_glUnmapBufferOES) ((GLenum) target); + return _res; +} + typedef GLvoid* (GL_APIENTRY* PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); /* Java->C glue code: * Java package: jogamp.opengl.es1.GLES1Impl diff --git a/make/config/jogl/gl-impl-CustomCCode-gles3.c b/make/config/jogl/gl-impl-CustomCCode-gles3.c index 2f3329bfa..ff1d42e23 100644 --- a/make/config/jogl/gl-impl-CustomCCode-gles3.c +++ b/make/config/jogl/gl-impl-CustomCCode-gles3.c @@ -1,4 +1,40 @@ +/* Java->C glue code: + * Java package: jogamp.opengl.es3.GLES3Impl + * Java method: void dispatch_glBufferData(int target, long size, java.nio.Buffer data, int usage) + * C function: void glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + */ +JNIEXPORT void JNICALL +Java_jogamp_opengl_es3_GLES3Impl_dispatch_1glBufferData(JNIEnv *env, jobject _unused, jint target, jlong size, jobject data, jint data_byte_offset, jboolean data_is_nio, jint usage, jlong procAddress) { + typedef void (GL_APIENTRY*_local_PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); + _local_PFNGLBUFFERDATAPROC ptr_glBufferData; + GLvoid * _data_ptr = NULL; + if ( NULL != data ) { + _data_ptr = (GLvoid *) ( JNI_TRUE == data_is_nio ? (*env)->GetDirectBufferAddress(env, data) : (*env)->GetPrimitiveArrayCritical(env, data, NULL) ); } + ptr_glBufferData = (_local_PFNGLBUFFERDATAPROC) (intptr_t) procAddress; + assert(ptr_glBufferData != NULL); + (* ptr_glBufferData) ((GLenum) target, (GLsizeiptr) size, (GLvoid *) (((char *) _data_ptr) + data_byte_offset), (GLenum) usage); + if ( JNI_FALSE == data_is_nio && NULL != data ) { + (*env)->ReleasePrimitiveArrayCritical(env, data, _data_ptr, JNI_ABORT); } +} + +/* Java->C glue code: + * Java package: jogamp.opengl.es3.GLES3Impl + * Java method: boolean dispatch_glUnmapBuffer(int target) + * C function: GLboolean glUnmapBuffer(GLenum target); + */ +JNIEXPORT jboolean JNICALL +Java_jogamp_opengl_es3_GLES3Impl_dispatch_1glUnmapBuffer(JNIEnv *env, jobject _unused, jint target, jlong procAddress) { + typedef GLboolean (GL_APIENTRY*_local_PFNGLUNMAPBUFFERPROC)(GLenum target); + _local_PFNGLUNMAPBUFFERPROC ptr_glUnmapBuffer; + GLboolean _res; + ptr_glUnmapBuffer = (_local_PFNGLUNMAPBUFFERPROC) (intptr_t) procAddress; + assert(ptr_glUnmapBuffer != NULL); + _res = (* ptr_glUnmapBuffer) ((GLenum) target); + return _res; +} + typedef GLvoid* (GL_APIENTRY* PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); + /* Java->C glue code: * Java package: jogamp.opengl.es3.GLES3Impl * Java method: long dispatch_glMapBuffer(int target, int access) diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index 4b1fc0977..f0246355e 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -6,23 +6,37 @@ @Override public final int glGetBoundBuffer(int target) { + return getBoundBuffer(target); + } + @Override + public final int getBoundBuffer(int target) { return bufferStateTracker.getBoundBufferObject(target, this); } @Override - public final long glGetBufferSize(int buffer) { - synchronized(bufferSizeTracker) { - return bufferSizeTracker.getDirectStateBufferSize(buffer, this); - } + public final long glGetBufferSize(int bufferName) { + return bufferObjectTracker.getBufferSize(bufferName); + } + @Override + public final GLBufferStorage getBufferStorage(int bufferName) { + return bufferObjectTracker.getBufferStorage(bufferName); } @Override public final boolean glIsVBOArrayBound() { + return isVBOArrayBound(); + } + @Override + public final boolean isVBOArrayBound() { return checkArrayVBOBound(false); } @Override public final boolean glIsVBOElementArrayBound() { + return isVBOElementArrayBound(); + } + @Override + public final boolean isVBOElementArrayBound() { return checkElementVBOBound(false); } @@ -130,101 +144,60 @@ return _context.getDefaultReadBuffer(); } - private final HashMap<MemoryObject, MemoryObject> arbMemCache = new HashMap<MemoryObject, MemoryObject>(); - - /** Entry point to C language function: <code> void * {@native glMapBuffer}(GLenum target, GLenum access); </code> <br>Part of <code>GL_VERSION_1_5</code>; <code>GL_OES_mapbuffer</code> */ - private final java.nio.ByteBuffer glMapBufferImpl(int target, boolean useRange, long offset, long length, int access, long glProcAddress) { - if (glProcAddress == 0) { - throw new GLException("Method \""+(useRange?"glMapBufferRange":"glMapBuffer")+"\" not available"); - } - final long addr, sz; - synchronized(bufferSizeTracker) { - sz = bufferSizeTracker.getBufferSize(bufferStateTracker, target, this); - if (0 == sz) { - return null; - } - if( !useRange ) { - length = sz; - offset = 0; - } else { - if( length + offset > sz ) { - throw new GLException("Out of range: offset "+offset+" + length "+length+" > size "+sz); - } - if( 0 > length || 0 > offset ) { - throw new GLException("Invalid values: offset "+offset+", length "+length); + private final GLStateTracker glStateTracker; + + // + // GLBufferObjectTracker Redirects + // + private final GLBufferObjectTracker bufferObjectTracker; + private final GLBufferStateTracker bufferStateTracker; + + private final jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch createBoundMutableStorageDispatch = + new jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch() { + public final void create(final int target, final long size, final Buffer data, final int mutableUsage, final long glProcAddress) { + final boolean data_is_direct = Buffers.isDirect(data); + dispatch_glBufferData(target, size, + data_is_direct ? data : Buffers.getArray(data), + data_is_direct ? Buffers.getDirectBufferByteOffset(data) : Buffers.getIndirectBufferByteOffset(data), + data_is_direct, mutableUsage, glProcAddress); } - if( 0 == length ) { - return null; + }; + private native void dispatch_glBufferData(int target, long size, Object data, int data_byte_offset, boolean data_is_direct, int usage, long procAddress); + + private final jogamp.opengl.GLBufferObjectTracker.UnmapBufferDispatch unmapBoundBufferDispatch = + new jogamp.opengl.GLBufferObjectTracker.UnmapBufferDispatch() { + public final boolean unmap(final int target, final long glProcAddress) { + return dispatch_glUnmapBuffer(target, glProcAddress); } - } - addr = useRange ? dispatch_glMapBufferRange(target, offset, length, access, glProcAddress) : - dispatch_glMapBuffer(target, access, glProcAddress); - } - if (0 == addr) { - return null; - } - final ByteBuffer buffer; - final MemoryObject memObj0 = new MemoryObject(addr, length); // object and key - final MemoryObject memObj1 = MemoryObject.getOrAddSafe(arbMemCache, memObj0); - if(memObj0 == memObj1) { - // just added .. - if(null != memObj0.getBuffer()) { - throw new InternalError(); - } - buffer = newDirectByteBuffer(addr, length); - Buffers.nativeOrder(buffer); - memObj0.setBuffer(buffer); - } else { - // already mapped - buffer = memObj1.getBuffer(); - if(null == buffer) { - throw new InternalError(); - } - } - buffer.position(0); - return buffer; + }; + private native boolean dispatch_glUnmapBuffer(int target, long procAddress); + + @Override + public final java.nio.ByteBuffer glMapBuffer(int target, int access) { + return mapBuffer(target, access).getMappedBuffer(); + } + + @Override + public final ByteBuffer glMapBufferRange(int target, long offset, long length, int access) { + return mapBufferRange(target, offset, length, access).getMappedBuffer(); } + + private final jogamp.opengl.GLBufferObjectTracker.MapBufferAllDispatch mapBoundBufferAllDispatch = + new jogamp.opengl.GLBufferObjectTracker.MapBufferAllDispatch() { + public final ByteBuffer allocNioByteBuffer(final long addr, final long length) { return newDirectByteBuffer(addr, length); } + public final long mapBuffer(final int target, final int access, final long glProcAddress) { + return dispatch_glMapBuffer(target, access, glProcAddress); + } + }; private native long dispatch_glMapBuffer(int target, int access, long glProcAddress); - private native long dispatch_glMapBufferRange(int target, long offset, long length, int access, long procAddress); - - - /** Entry point to C language function: <code> GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access); </code> <br>Part of <code>GL_EXT_direct_state_access</code> */ - private final java.nio.ByteBuffer glMapNamedBufferImpl(int bufferName, int access, long glProcAddress) { - if (glProcAddress == 0) { - throw new GLException("Method \"glMapNamedBufferEXT\" not available"); - } - final long addr, sz; - synchronized(bufferSizeTracker) { - sz = bufferSizeTracker.getDirectStateBufferSize(bufferName, this); - if (0 == sz) { - return null; - } - addr = dispatch_glMapNamedBufferEXT(bufferName, access, glProcAddress); - } - if (0 == addr) { - return null; - } - final ByteBuffer buffer; - final MemoryObject memObj0 = new MemoryObject(addr, sz); // object and key - final MemoryObject memObj1 = MemoryObject.getOrAddSafe(arbMemCache, memObj0); - if(memObj0 == memObj1) { - // just added .. - if(null != memObj0.getBuffer()) { - throw new InternalError(); - } - buffer = newDirectByteBuffer(addr, sz); - Buffers.nativeOrder(buffer); - memObj0.setBuffer(buffer); - } else { - // already mapped - buffer = memObj1.getBuffer(); - if(null == buffer) { - throw new InternalError(); - } - } - buffer.position(0); - return buffer; - } - private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long procAddress); + + private final jogamp.opengl.GLBufferObjectTracker.MapBufferRangeDispatch mapBoundBufferRangeDispatch = + new jogamp.opengl.GLBufferObjectTracker.MapBufferRangeDispatch() { + public final ByteBuffer allocNioByteBuffer(final long addr, final long length) { return newDirectByteBuffer(addr, length); } + public final long mapBuffer(final int target, final long offset, final long length, final int access, final long glProcAddress) { + return dispatch_glMapBufferRange(target, offset, length, access, glProcAddress); + } + }; + private native long dispatch_glMapBufferRange(int target, long offset, long length, int access, long glProcAddress); private native ByteBuffer newDirectByteBuffer(long addr, long capacity); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java index e7389de10..f0adb5328 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java @@ -18,11 +18,11 @@ public void setObjectTracker(GLObjectTracker tracker) { public GL4bcImpl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); + this.bufferObjectTracker = context.getBufferObjectTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; + this.bufferObjectTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -280,10 +280,6 @@ public final void glFreeMemoryNV(java.nio.ByteBuffer pointer) { // Helpers for ensuring the correct amount of texture data // -private final GLBufferSizeTracker bufferSizeTracker; -private final GLBufferStateTracker bufferStateTracker; -private final GLStateTracker glStateTracker; - private boolean haveARBPixelBufferObject; private boolean haveEXTPixelBufferObject; private boolean haveGL15; @@ -431,67 +427,207 @@ private final boolean checkPackPBOBound(boolean throwException) { @Override public final boolean glIsPBOPackBound() { + return isPBOPackBound(); +} +@Override +public final boolean isPBOPackBound() { return checkPackPBOBound(false); } @Override public final boolean glIsPBOUnpackBound() { + return isPBOUnpackBound(); +} +@Override +public final boolean isPBOUnpackBound() { return checkUnpackPBOBound(false); } -/** Entry point to C language function: <code> void * {@native glMapBuffer}(GLenum target, GLenum access); </code> <br>Part of <code>GL_VERSION_1_5</code>; <code>GL_OES_mapbuffer</code> */ -public final java.nio.ByteBuffer glMapBuffer(int target, int access) { - return glMapBufferImpl(target, false, 0, 0, access, ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer); +@Override +public final void glVertexPointer(GLArrayData array) { + if(array.getComponentCount()==0) return; + if(array.isVBO()) { + glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); + } else { + glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); + } } +@Override +public final void glColorPointer(GLArrayData array) { + if(array.getComponentCount()==0) return; + if(array.isVBO()) { + glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); + } else { + glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); + } -/** Entry point to C language function: <code> void * {@native glMapBufferRange}(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); </code> <br>Part of <code>GL_ES_VERSION_3_0</code>, <code>GL_VERSION_3_0</code>; <code>GL_EXT_map_buffer_range</code> */ -public final ByteBuffer glMapBufferRange(int target, long offset, long length, int access) { - return glMapBufferImpl(target, true, offset, length, access, ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange); } - -/** Entry point to C language function: <code> GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access); </code> <br>Part of <code>GL_EXT_direct_state_access</code> */ -public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { - return glMapNamedBufferImpl(bufferName, access, ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT); +@Override +public final void glNormalPointer(GLArrayData array) { + if(array.getComponentCount()==0) return; + if(array.getComponentCount()!=3) { + throw new GLException("Only 3 components per normal allowed"); + } + if(array.isVBO()) { + glNormalPointer(array.getComponentType(), array.getStride(), array.getVBOOffset()); + } else { + glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); + } +} +@Override +public final void glTexCoordPointer(GLArrayData array) { + if(array.getComponentCount()==0) return; + if(array.isVBO()) { + glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); + } else { + glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); + } } - @Override - public final void glVertexPointer(GLArrayData array) { - if(array.getComponentCount()==0) return; - if(array.isVBO()) { - glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); - } else { - glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); - } +// +// GLBufferObjectTracker Redirects +// + +@Override +public final void glBufferData(int target, long size, Buffer data, int usage) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glBufferData; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glBufferData")); + } + bufferObjectTracker.createBufferStorage(bufferStateTracker, this, + target, size, data, usage, 0 /* immutableFlags */, + createBoundMutableStorageDispatch, glProcAddress); +} +/** FIXME Add for OpenGL 4.4 +@Override +public final void glBufferStorage(int target, long size, Buffer data, int flags) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glBufferStorage; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glBufferStorage")); } - @Override - public final void glColorPointer(GLArrayData array) { - if(array.getComponentCount()==0) return; - if(array.isVBO()) { - glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); - } else { - glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); - } + bufferObjectTracker.createBufferStorage(bufferStateTracker, this, + target, size, data, 0 * mutableUsage *, flags, + createBoundImmutableStorageDispatch, glProcAddress); +} +private final jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch createBoundImmutableStorageDispatch = + new jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch() { + public final void create(final int target, final long size, final Buffer data, final int immutableFlags, final long glProcAddress) { + final boolean data_is_direct = Buffers.isDirect(data); + dispatch_glBufferStorage(target, size, + data_is_direct ? data : Buffers.getArray(data), + data_is_direct ? Buffers.getDirectBufferByteOffset(data) : Buffers.getIndirectBufferByteOffset(data), + data_is_direct, immutableFlags, glProcAddress); + } + }; +private native void dispatch_glBufferStorage(int target, long size, Object data, int data_byte_offset, boolean data_is_direct, int flags, long procAddress); + */ +@Override +public final void glNamedBufferDataEXT(int buffer, long size, Buffer data, int usage) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glNamedBufferDataEXT; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glNamedBufferDataEXT")); } - @Override - public final void glNormalPointer(GLArrayData array) { - if(array.getComponentCount()==0) return; - if(array.getComponentCount()!=3) { - throw new GLException("Only 3 components per normal allowed"); - } - if(array.isVBO()) { - glNormalPointer(array.getComponentType(), array.getStride(), array.getVBOOffset()); - } else { - glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); - } + bufferObjectTracker.createBufferStorage(this, + buffer, size, data, usage, 0 /* immutableFlags */, + createNamedStorageDispatch, glProcAddress); +} +private final jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch createNamedStorageDispatch = + new jogamp.opengl.GLBufferObjectTracker.CreateStorageDispatch() { + public final void create(final int buffer, final long size, final Buffer data, final int mutableUsage, final long glProcAddress) { + final boolean data_is_direct = Buffers.isDirect(data); + dispatch_glNamedBufferDataEXT(buffer, size, + data_is_direct ? data : Buffers.getArray(data), + data_is_direct ? Buffers.getDirectBufferByteOffset(data) : Buffers.getIndirectBufferByteOffset(data), + data_is_direct, mutableUsage, glProcAddress); + } + }; +private native void dispatch_glNamedBufferDataEXT(int buffer, long size, Object data, int data_byte_offset, boolean data_is_direct, int usage, long procAddress); + +@Override +public boolean glUnmapBuffer(int target) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glUnmapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glUnmapBuffer")); } - @Override - public final void glTexCoordPointer(GLArrayData array) { - if(array.getComponentCount()==0) return; - if(array.isVBO()) { - glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); - } else { - glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); - } + return bufferObjectTracker.unmapBuffer(bufferStateTracker, this, target, unmapBoundBufferDispatch, glProcAddress); +} + +@Override +public boolean glUnmapNamedBufferEXT(int buffer) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glUnmapNamedBufferEXT; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glUnmapNamedBufferEXT")); } + return bufferObjectTracker.unmapBuffer(buffer, unmapNamedBufferDispatch, glProcAddress); +} +private final jogamp.opengl.GLBufferObjectTracker.UnmapBufferDispatch unmapNamedBufferDispatch = + new jogamp.opengl.GLBufferObjectTracker.UnmapBufferDispatch() { + public final boolean unmap(final int buffer, final long glProcAddress) { + return dispatch_glUnmapNamedBufferEXT(buffer, glProcAddress); + } + }; +private native boolean dispatch_glUnmapNamedBufferEXT(int buffer, long procAddress); + +@Override +public final GLBufferStorage mapBuffer(final int target, final int access) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBuffer\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, access, mapBoundBufferAllDispatch, glProcAddress); +} +@Override +public final GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBufferRange\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, offset, length, access, mapBoundBufferRangeDispatch, glProcAddress); +} + +@Override +public final GLBufferStorage mapNamedBuffer(final int bufferName, final int access) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapNamedBufferEXT\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferName, access, mapNamedBufferAllDispatch, glProcAddress); +} +private final jogamp.opengl.GLBufferObjectTracker.MapBufferAllDispatch mapNamedBufferAllDispatch = + new jogamp.opengl.GLBufferObjectTracker.MapBufferAllDispatch() { + public final ByteBuffer allocNioByteBuffer(final long addr, final long length) { return newDirectByteBuffer(addr, length); } + public final long mapBuffer(final int bufferName, final int access, final long glProcAddress) { + return dispatch_glMapNamedBufferEXT(bufferName, access, glProcAddress); + } + }; +private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long glProcAddress); + +@Override +public final GLBufferStorage mapNamedBufferRange(final int bufferName, final long offset, final long length, final int access) { + final long glProcAddress = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferRangeEXT; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapNamedBufferRangeEXT\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferName, offset, length, access, mapNamedBufferRangeDispatch, glProcAddress); +} +private final jogamp.opengl.GLBufferObjectTracker.MapBufferRangeDispatch mapNamedBufferRangeDispatch = + new jogamp.opengl.GLBufferObjectTracker.MapBufferRangeDispatch() { + public final ByteBuffer allocNioByteBuffer(final long addr, final long length) { return newDirectByteBuffer(addr, length); } + public final long mapBuffer(final int bufferName, final long offset, final long length, final int access, final long glProcAddress) { + return dispatch_glMapNamedBufferRangeEXT(bufferName, offset, length, access, glProcAddress); + } + }; +private native long dispatch_glMapNamedBufferRangeEXT(int buffer, long offset, long length, int access, long procAddress); + +@Override +public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { + return mapNamedBuffer(bufferName, access).getMappedBuffer(); +} + +@Override +public final ByteBuffer glMapNamedBufferRangeEXT(int bufferName, long offset, long length, int access) { + return mapNamedBufferRange(bufferName, offset, length, access).getMappedBuffer(); +} + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java index 8d5dcc7a5..6a7e12ca1 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java @@ -1,11 +1,11 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); + this.bufferObjectTracker = context.getBufferObjectTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; + this.bufferObjectTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -199,10 +199,6 @@ public final GL2GL3 getGL2GL3() throws GLException { // Helpers for ensuring the correct amount of texture data // -private final GLBufferSizeTracker bufferSizeTracker; -private final GLBufferStateTracker bufferStateTracker; -private final GLStateTracker glStateTracker; - private final boolean checkBufferObject(boolean bound, int state, String kind, boolean throwException) { @@ -269,16 +265,6 @@ private final boolean checkPackPBOBound(boolean throwException) { return false; } -/** Entry point to C language function: <code> void * {@native glMapBuffer}(GLenum target, GLenum access); </code> <br>Part of <code>GL_VERSION_1_5</code>; <code>GL_OES_mapbuffer</code> */ -public final java.nio.ByteBuffer glMapBuffer(int target, int access) { - return glMapBufferImpl(target, false, 0, 0, access, ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer); -} - -/** Entry point to C language function: <code> void * {@native glMapBufferRange}(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); </code> <br>Part of <code>GL_ES_VERSION_3_0</code>, <code>GL_VERSION_3_0</code>; <code>GL_EXT_map_buffer_range</code> */ -public final ByteBuffer glMapBufferRange(int target, long offset, long length, int access) { - return glMapBufferImpl(target, true, offset, length, access, ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange); -} - @Override public final void glVertexPointer(GLArrayData array) { if(array.getComponentCount()==0) return; @@ -320,3 +306,44 @@ public final void glTexCoordPointer(GLArrayData array) { } } +// +// GLBufferObjectTracker Redirects +// + +@Override +public final void glBufferData(int target, long size, Buffer data, int usage) { + final long glProcAddress = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glBufferData; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glBufferData")); + } + bufferObjectTracker.createBufferStorage(bufferStateTracker, this, + target, size, data, usage, 0 /* immutableFlags */, + createBoundMutableStorageDispatch, glProcAddress); +} + +@Override +public boolean glUnmapBuffer(int target) { + final long glProcAddress = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glUnmapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glUnmapBuffer")); + } + return bufferObjectTracker.unmapBuffer(bufferStateTracker, this, target, unmapBoundBufferDispatch, glProcAddress); +} + +@Override +public final GLBufferStorage mapBuffer(final int target, final int access) { + final long glProcAddress = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBuffer\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, access, mapBoundBufferAllDispatch, glProcAddress); +} +@Override +public final GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) { + final long glProcAddress = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBufferRange\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, offset, length, access, mapBoundBufferRangeDispatch, glProcAddress); +} + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles3.java b/make/config/jogl/gl-impl-CustomJavaCode-gles3.java index d5ad16873..a5c0d1998 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles3.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles3.java @@ -2,11 +2,11 @@ public GLES3Impl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); + this.bufferObjectTracker = context.getBufferObjectTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; + this.bufferObjectTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -211,9 +211,6 @@ public final GL2GL3 getGL2GL3() throws GLException { // private final boolean _isES3; -private final GLBufferSizeTracker bufferSizeTracker; -private final GLBufferStateTracker bufferStateTracker; -private final GLStateTracker glStateTracker; private final boolean checkBufferObject(boolean extensionAvail, boolean allowVAO, @@ -333,22 +330,20 @@ private final boolean checkPackPBOBound(boolean throwException) { @Override public final boolean glIsPBOPackBound() { + return isPBOPackBound(); +} +@Override +public final boolean isPBOPackBound() { return checkPackPBOBound(false); } @Override public final boolean glIsPBOUnpackBound() { - return checkUnpackPBOBound(false); + return isPBOUnpackBound(); } - -/** Entry point to C language function: <code> void * {@native glMapBuffer}(GLenum target, GLenum access); </code> <br>Part of <code>GL_VERSION_1_5</code>; <code>GL_OES_mapbuffer</code> */ -public final java.nio.ByteBuffer glMapBuffer(int target, int access) { - return glMapBufferImpl(target, false, 0, 0, access, ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer); -} - -/** Entry point to C language function: <code> void * {@native glMapBufferRange}(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); </code> <br>Part of <code>GL_ES_VERSION_3_0</code>, <code>GL_VERSION_3_0</code>; <code>GL_EXT_map_buffer_range</code> */ -public final ByteBuffer glMapBufferRange(int target, long offset, long length, int access) { - return glMapBufferImpl(target, true, offset, length, access, ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange); +@Override +public final boolean isPBOUnpackBound() { + return checkUnpackPBOBound(false); } @Override @@ -361,3 +356,45 @@ public final void glDepthRange(double zNear, double zFar) { glDepthRangef((float)zNear, (float)zFar); } +// +// GLBufferObjectTracker Redirects +// + +@Override +public final void glBufferData(int target, long size, Buffer data, int usage) { + final long glProcAddress = ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glBufferData; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glBufferData")); + } + bufferObjectTracker.createBufferStorage(bufferStateTracker, this, + target, size, data, usage, 0 /* immutableFlags */, + createBoundMutableStorageDispatch, glProcAddress); +} + +@Override +public boolean glUnmapBuffer(int target) { + final long glProcAddress = ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glUnmapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException(String.format("Method \"%s\" not available", "glUnmapBuffer")); + } + return bufferObjectTracker.unmapBuffer(bufferStateTracker, this, target, unmapBoundBufferDispatch, glProcAddress); +} + +@Override +public final GLBufferStorage mapBuffer(final int target, final int access) { + final long glProcAddress = ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBuffer\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, access, mapBoundBufferAllDispatch, glProcAddress); +} +@Override +public final GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) { + final long glProcAddress = ((GLES3ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBufferRange; + if ( 0 == glProcAddress ) { + throw new GLException("Method \"glMapBufferRange\" not available"); + } + return bufferObjectTracker.mapBuffer(bufferStateTracker, this, target, offset, length, access, mapBoundBufferRangeDispatch, glProcAddress); +} + + diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 649256393..6bc1d4eb3 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -103,13 +103,17 @@ function jrun() { #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.TraceGL -Djogl.debug.GLBufferStateTracker" #D_ARGS="-Djogl.debug.FBObject" + #D_ARGS="-Djogl.debug.GLBufferStateTracker -Djogl.debug.GLBufferObjectTracker -Djogamp.debug.Lock -Djogamp.common.utils.locks.Lock.timeout=600000 -Dnewt.debug.EDT" + #D_ARGS="-Djogl.debug.GLBufferStateTracker -Djogl.debug.GLBufferObjectTracker" + #D_ARGS="-Djogl.debug.GLBufferObjectTracker" + #D_ARGS="-Djogl.debug.GLBufferObjectTracker -Djogl.debug.GLArrayData -Djogl.debug.TraceGL -Djogl.debug.DebugGL" #D_ARGS="-Djogl.debug.GLSLCode" #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL" #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window" #D_ARGS="-Dnativewindow.debug.JAWT -Djogl.debug.GLCanvas" #D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource" - D_ARGS="-Dnativewindow.debug.JAWT" + #D_ARGS="-Dnativewindow.debug.JAWT" #D_ARGS="-Djogl.debug.GLContext.TraceSwitch" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLContext.TraceSwitch" #D_ARGS="-Djogl.debug.FixedFuncPipeline -Djogl.debug.GLSLCode" @@ -208,6 +212,7 @@ function jrun() { #D_ARGS="-Xprof" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl" + #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel -Djogl.gljpanel.noglsl -Djogl.gljpanel.awtverticalflip" #D_ARGS="-Djogl.debug.GLJPanel -Djogl.debug.DebugGL" #D_ARGS="-Djogl.gljpanel.noverticalflip" #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Animator" @@ -390,7 +395,13 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* + #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestRedSquareES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT0 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 $* + #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAONEWT $* @@ -536,7 +547,7 @@ function testawtswt() { # OK (X11, OSX) #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos03cB849AWT $* -testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos01AWT $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos01AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos02AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816GLCanvasFrameHoppingB849B889AWT $* #testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug816OSXCALayerPos04aAWT $* diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java index df60d2f73..023913d7b 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildComposablePipeline.java @@ -41,6 +41,7 @@ package com.jogamp.gluegen.opengl; import com.jogamp.gluegen.CodeGenUtils; import com.jogamp.gluegen.JavaType; + import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; @@ -50,6 +51,7 @@ import java.lang.reflect.Method; import java.nio.Buffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -82,6 +84,16 @@ public class BuildComposablePipeline { */ public static final int GEN_GL_IDENTITY_BY_ASSIGNABLE_CLASS = 1 << 4; + private static final HashMap<String, String> addedGLHooks = new HashMap<String, String>(); + private static final String[] addedGLHookMethodNames = new String[] { + "mapBuffer", "mapBufferRange", + "mapNamedBuffer", "mapNamedBufferRange" }; + static { + for(int i=0; i<addedGLHookMethodNames.length; i++) { + addedGLHooks.put(addedGLHookMethodNames[i], addedGLHookMethodNames[i]); + } + } + int mode; private final String outputDir; private final String outputPackage; @@ -200,8 +212,11 @@ public class BuildComposablePipeline { // Don't hook methods which aren't real GL methods, // such as the synthetic "isGL2ES2" "getGL2ES2" final String name = method.getName(); - boolean runHooks = name.startsWith("gl"); - if ( !name.startsWith("getGL") && !name.startsWith("isGL") && !name.equals("getDownstreamGL") && !name.equals("toString") ) { + if ( !name.startsWith("getGL") && + !name.startsWith("isGL") && + !name.equals("getDownstreamGL") && + !name.equals("toString") ) { + final boolean runHooks = name.startsWith("gl") || addedGLHooks.containsKey(name); publicMethodsPlain.add(new PlainMethod(method, runHooks)); } } diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index a19a99196..3ac12f0a1 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -505,26 +505,97 @@ public interface GLBase { public void glDepthRange(double zNear, double zFar); /** - * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, .. - * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound. + * @deprecated Avoid original GL API namespace conflict. Use {@link #getBoundBuffer(int)} */ public int glGetBoundBuffer(int target); + /** + * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, .. + * @return the GL buffer name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound. + * @see #getBufferStorage(int) + */ + public int getBoundBuffer(int target); /** - * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example. - * @return the size of the given GL buffer + * @deprecated Use {@link #getBufferStorage(int)}. */ - public long glGetBufferSize(int buffer); + public long glGetBufferSize(int bufferName); + /** + * @param bufferName a GL buffer name, generated with e.g. {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)}. + * @return the size of the given GL buffer storage, see {@link GLBufferStorage} + * @see #getBoundBuffer(int) + */ + public GLBufferStorage getBufferStorage(int bufferName); /** - * @return true if a VBO is bound to {@link GL#GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBuffer(int, int) glMapBuffer(..)} implementation. + * <p> + * Throws a {@link GLException} if GL-function constraints are not met. + * </p> + * <p> + * {@link GL#glMapBuffer(int, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}. + * </p> + * <p> + * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}. + * </p> + * <p> + * A null native mapping result indicating an error will + * not cause a GLException but returns the unmapped {@link GLBufferStorage}. + * This allows the user to handle this case. + * </p> + * @param target denotes the buffer via it's bound target + * @param access the mapping access mode + * @throws GLException if buffer is not bound to target + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + */ + public GLBufferStorage mapBuffer(int target, int access) throws GLException; + + /** + * Returns the {@link GLBufferStorage} instance as mapped via OpenGL's native {@link GL#glMapBufferRange(int, long, long, int) glMapBufferRange(..)} implementation. + * <p> + * Throws a {@link GLException} if GL-function constraints are not met. + * </p> + * <p> + * {@link GL#glMapBufferRange(int, long, long, int)} wrapper calls this method and returns {@link GLBufferStorage#getMappedBuffer()}. + * </p> + * <p> + * A zero {@link GLBufferStorage#getSize()} will avoid a native call and returns the unmapped {@link GLBufferStorage}. + * </p> + * <p> + * A null native mapping result indicating an error will + * not cause a GLException but returns the unmapped {@link GLBufferStorage}. + * This allows the user to handle this case. + * </p> + * @param target denotes the buffer via it's bound target + * @param offset offset of the mapped buffer's storage + * @param length length of the mapped buffer's storage + * @param access the mapping access mode + * @throws GLException if buffer is not bound to target + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + * @throws GLException if buffer mapping range does not fit, incl. offset + */ + public GLBufferStorage mapBufferRange(final int target, final long offset, final long length, final int access) throws GLException; + + /** + * @deprecated Avoid original GL API namespace conflict. Use {@link #isVBOArrayBound()} */ public boolean glIsVBOArrayBound(); + /** + * @return true if a VBO is bound to {@link GL#GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean isVBOArrayBound(); /** - * @return true if a VBO is bound to {@link GL#GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + * @deprecated Avoid original GL API namespace conflict. Use {@link #isVBOElementArrayBound()} */ public boolean glIsVBOElementArrayBound(); + /** + * @return true if a VBO is bound to {@link GL#GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean isVBOElementArrayBound(); /** * Return the framebuffer name bound to this context, diff --git a/src/jogl/classes/javax/media/opengl/GLBufferStorage.java b/src/jogl/classes/javax/media/opengl/GLBufferStorage.java new file mode 100644 index 000000000..929ecf60a --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLBufferStorage.java @@ -0,0 +1,150 @@ +/** + * Copyright 2014 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 javax.media.opengl; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +/** + * OpenGL buffer storage object reflecting it's + * <ul> + * <li>storage size</li> + * <li>storage memory if mapped</li> + * <li>mutable usage or immutable flags</li> + * </ul> + * <p> + * Buffer storage is created via: + * <ul> + * <li><code>glBufferStorage</code> - storage creation with target</li> + * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation with target</li> + * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li> + * </ul> + * Note that storage <i>recreation</i> as mentioned above also invalidate a previous storage instance, + * i.e. disposed the buffer's current storage if exist and attaches a new storage instance. + * </p> + * <p> + * Buffer storage is disposed via: + * <ul> + * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - explicit, direct, via {@link #notifyBuffersDeleted(int, IntBuffer)} or {@link #notifyBuffersDeleted(int, int[], int)}</li> + * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li> + * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li> + * </ul> + * </p> + * <p> + * GL buffer storage is mapped via + * <ul> + * + * <li>{@link GL#mapBuffer(int, int)}</li> + * <li>{@link GL#mapBufferRange(int, long, long, int)}</li> + * <li>{@link GL2#mapNamedBuffer(int, int)}</li> + * <li>{@link GL2#mapNamedBufferRange(int, long, long, int)}</li> + * </ul> + * </p> + * <p> + * GL buffer storage is unmapped via + * <ul> + * <li>{@link GL#glUnmapBuffer(int)} - explicit via target</li> + * <li>{@link GL2#glUnmapNamedBufferEXT(int)} - explicit direct</li> + * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li> + * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li> + * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - buffer deletion</li> + * </ul> + * </p> + */ +public abstract class GLBufferStorage { + private final int name; + private final long size; + private final int mutableUsage; + private final int immutableFlags; + protected ByteBuffer mappedBuffer; + + protected GLBufferStorage(final int name, final long size, final int mutableUsage, final int immutableFlags) { + this.name = name; + this.size = size; + this.mutableUsage = mutableUsage; + this.immutableFlags = immutableFlags; + this.mappedBuffer = null; + } + + /** Return the buffer name */ + public final int getName() { return name; } + + /** Return the buffer's storage size. */ + public final long getSize() { return size; } + + /** + * Returns <code>true</code> if buffer's storage is mutable, i.e. + * created via {@link GL#glBufferData(int, long, java.nio.Buffer, int)}. + * <p> + * Returns <code>false</code> if buffer's storage is immutable, i.e. + * created via <code>glBufferStorage</code>. FIXME: Add GL 4.4 support! + * </p> + * @return + */ + public final boolean isMutableStorage() { return 0 != mutableUsage; } + + /** + * Returns the mutable storage usage or 0 if storage is not {@link #isMutableStorage() mutable}. + */ + public final int getMutableUsage() { return mutableUsage; } + + /** + * Returns the immutable storage flags, invalid if storage is {@link #isMutableStorage() mutable}. + */ + public final int getImmutableFlags() { return immutableFlags; } + + /** + * Returns the mapped ByteBuffer, or null if not mapped. + * Mapping may occur via: + * <ul> + * <li>{@link GL#glMapBuffer(int, int)}</li> + * <li>{@link GL#glMapBufferRange(int, long, long, int)}</li> + * <li>{@link GL2#glMapNamedBufferEXT(int, int)}</li> + * <li>{@link GL2#glMapNamedBufferRangeEXT(int, long, long, int)} + * </ul> + */ + public final ByteBuffer getMappedBuffer() { return mappedBuffer; } + + public final String toString() { + return toString(false); + } + public final String toString(final boolean skipMappedBuffer) { + final String s0; + if( isMutableStorage() ) { + s0 = String.format("%s[name %s, size %d, mutable usage 0x%X", msgClazzName, name, size, mutableUsage); + } else { + s0 = String.format("%s[name %s, size %d, immutable flags 0x%X", msgClazzName, name, size, immutableFlags); + } + if(skipMappedBuffer) { + return s0+"]"; + } else { + return s0+", mapped "+mappedBuffer+"]"; + } + } + private final String msgClazzName = "GLBufferStorage"; +} diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index bec62c30d..0b0ed8e0d 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -1622,8 +1622,8 @@ public abstract class GLContext { final Integer valI = deviceVersionAvailable.get(key); if(null != valI) { final int bits32 = valI.intValue(); - final int major = ( bits32 & 0xFF000000 ) >> 24 ; - final int minor = ( bits32 & 0x00FF0000 ) >> 16 ; + final int major = ( bits32 & 0xFF000000 ) >>> 24 ; + final int minor = ( bits32 & 0x00FF0000 ) >>> 16 ; final int ctp = ( bits32 & 0x0000FFFF ) ; sb.append(GLContext.getGLVersion(major, minor, ctp, null)); } else { @@ -1668,10 +1668,10 @@ public abstract class GLContext { final int bits32 = valI.intValue(); if(null!=major) { - major[0] = ( bits32 & 0xFF000000 ) >> 24 ; + major[0] = ( bits32 & 0xFF000000 ) >>> 24 ; } if(null!=minor) { - minor[0] = ( bits32 & 0x00FF0000 ) >> 16 ; + minor[0] = ( bits32 & 0x00FF0000 ) >>> 16 ; } if(null!=ctp) { ctp[0] = ( bits32 & 0x0000FFFF ) ; diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java new file mode 100644 index 000000000..289884b5c --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 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: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package jogamp.opengl; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import javax.media.opengl.*; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.common.util.IntObjectHashMap; + +/** + * Tracking of {@link GLBufferStorage} instances via GL API callbacks. + * <p> + * See {@link GLBufferStorage} for generic details. + * </p> + * <p> + * Buffer storage is created via + * <ul> + * <li><code>glBufferStorage</code> - storage creation with target via {@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}</li> + * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation with target via {@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}</li> + * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct, via {@link #createBufferStorage(GL, int, long, Buffer, int, CreateStorageDispatch, long)}</li> + * </ul> + * Note that storage <i>recreation</i> as mentioned above also invalidate a previous storage instance, + * i.e. disposed the buffer's current storage if exist and attaches a new storage instance. + * </p> + * <p> + * Buffers storage is disposed via + * <ul> + * <li>{@link GL#glDeleteBuffers(int, IntBuffer)} - explicit, direct, via {@link #notifyBuffersDeleted(int, IntBuffer)} or {@link #notifyBuffersDeleted(int, int[], int)}</li> + * <li>{@link GL#glBufferData(int, long, java.nio.Buffer, int)} - storage recreation via target</li> + * <li>{@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} - storage recreation, direct</li> + * </ul> + * </p> + * + * <p> + * Implementation throws a {@link GLException} in all <i>construction</i> methods as listed below, + * if GL-function constraints are not met. <code>createBufferStorage</code> also throws an exception + * if the native GL-function fails. + * <ul> + * <li>{@link #createBufferStorage(GLBufferStateTracker, GL, int, long, Buffer, int, int, CreateStorageDispatch, long)}, etc ..</li> + * <li>{@link #mapBuffer(GLBufferStateTracker, GL, int, int, MapBufferAllDispatch, long)}, etc ..</li> + * </ul> + * In <i>destruction</i> and informal methods, i.e. all others, implementation only issues a WARNING debug message, if enabled. + * </p> + * + * <p> + * Buffer mapping methods like {@link GL#mapBuffer(int, int)} ..., + * require knowledge of the buffer's storage size as determined via it's creation with + * {@link GL#glBufferData(int, long, java.nio.Buffer, int)} .... + * </p> + * <p> + * Hence we track the OpenGL buffer's {@link GLBufferStorage} to be able to + * access the buffer's storage size. The tracked {@link GLBufferStorage} instances + * also allow users to conveniently access details of their created and maybe mapped buffer storage. + * </p> + * <p> + * The {@link GLBufferObjectTracker} and it's tracked {@link GLBufferStorage} instances + * maybe shared across multiple OpenGL context, hence this class is thread safe and employs synchronization. + * </p> + * <p> + * Implementation requires and utilizes a local {@link GLBufferStateTracker} + * to resolve the actual buffer-name bound to the given target. + * </p> + * <p> + * Note: This tracker requires to be notified about all OpenGL buffer storage operations, + * as well as the local {@link GLBufferStateTracker} to be notified about all + * OpenGL buffer binding operations. + * Hence buffer storage cannot be accessed properly if managed via native code. + * </p> + */ +public class GLBufferObjectTracker { + protected static final boolean DEBUG; + + static { + Debug.initSingleton(); + DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferObjectTracker", true); + } + + static final class GLBufferStorageImpl extends GLBufferStorage { + GLBufferStorageImpl(final int name, final long size, final int mutableUsage, final int immutableFlags) { + super(name, size, mutableUsage, immutableFlags); + } + final void setMappedBuffer(final ByteBuffer bb) { + if (DEBUG) { + System.err.printf("%s.GLBufferStorage.setMappedBuffer: %s: %s -> %s%n", msgClazzName, toString(true), mappedBuffer, bb); + } + mappedBuffer = bb; + } + } + + /** + * Map from buffer names to GLBufferObject. + */ + private final IntObjectHashMap bufferName2StorageMap; + + public GLBufferObjectTracker() { + bufferName2StorageMap = new IntObjectHashMap(); + bufferName2StorageMap.setKeyNotFoundValue(null); + } + + public static interface CreateStorageDispatch { + void create(final int targetOrBufferName, final long size, final Buffer data, final int mutableUsageOrImmutableFlags, final long glProcAddress); + } + + /** + * Must be called when [re]creating the GL buffer object via <code>glBufferStorage</code> and {@link GL#glBufferData(int, long, java.nio.Buffer, int)}, + * i.e. implies destruction of the buffer. + * + * @param bufferStateTracker + * @param caller + * @param target + * @param size + * @param mutableUsage <code>glBufferData</code>, <code>glNamedBufferDataEXT</code> usage + * @param immutableFlags <code>glBufferStorage</code> flags + * @throws GLException if buffer is not bound to target + * @throws GLException if size is less-or-eqaul zero for <code>glBufferStorage</code>, or size is less-than zero otherwise + * @throws GLException if a native GL-Error occurs + */ + public synchronized final void createBufferStorage(final GLBufferStateTracker bufferStateTracker, final GL caller, + final int target, final long size, final Buffer data, int mutableUsage, int immutableFlags, + final CreateStorageDispatch dispatch, final long glProcAddress) throws GLException { + final int glerrPre = caller.glGetError(); // clear + if (DEBUG && GL.GL_NO_ERROR != glerrPre) { + System.err.printf("%s.%s glerr-pre 0x%X%n", msgClazzName, msgCreateBound, glerrPre); + } + final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller); + if ( 0 == bufferName ) { + throw new GLException(String.format("%s: Buffer for target 0x%X not bound", GL_INVALID_OPERATION, target)); + } + final boolean mutableBuffer = 0 != mutableUsage; + final boolean invalidSize = ( mutableBuffer && 0 > size ) // glBufferData, glNamedBufferDataEXT + || ( !mutableBuffer && 0 >= size ); // glBufferStorage + if( invalidSize ) { + throw new GLException(String.format("%s: Invalid size %d for buffer %d on target 0x%X", GL_INVALID_VALUE, size, bufferName, target)); + } + + dispatch.create(target, size, data, mutableBuffer ? mutableUsage : immutableFlags, glProcAddress); + final int glerrPost = caller.glGetError(); // be safe, catch failure! + if(GL.GL_NO_ERROR != glerrPost) { + throw new GLException(String.format("GL-Error 0x%X while creating %s storage for target 0x%X -> buffer %d of size %d with data %s", + glerrPost, mutableBuffer ? "mutable" : "immutable", target, bufferName, size, data)); + } + final GLBufferStorageImpl objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, immutableFlags); + final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, objNew); + if (DEBUG) { + System.err.printf("%s.%s target: 0x%X -> %d: %s -> %s%n", msgClazzName, msgCreateBound, target, bufferName, objOld, objNew); + } + if( null != objOld ) { + objOld.setMappedBuffer(null); + } + } + + /** + * Must be called when [re]creating the GL buffer object via {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)}, + * i.e. implies destruction of the buffer. + * + * @param bufferName + * @param size + * @param mutableUsage + * @throws GLException if size is less-than zero + * @throws GLException if a native GL-Error occurs + */ + public synchronized final void createBufferStorage(final GL caller, + final int bufferName, final long size, final Buffer data, final int mutableUsage, int immutableFlags, + final CreateStorageDispatch dispatch, final long glProcAddress) throws GLException { + final int glerrPre = caller.glGetError(); // clear + if (DEBUG && GL.GL_NO_ERROR != glerrPre) { + System.err.printf("%s.%s glerr-pre 0x%X%n", msgClazzName, msgCreateNamed, glerrPre); + } + if ( 0 > size ) { // glBufferData, glNamedBufferDataEXT + throw new GLException(String.format("%s: Invalid size %d for buffer %d", GL_INVALID_VALUE, size, bufferName)); + } + final boolean mutableBuffer = 0 != mutableUsage; + if( !mutableBuffer ) { + throw new InternalError("Immutable glNamedBufferStorageEXT not supported yet"); + } + dispatch.create(bufferName, size, data, mutableUsage, glProcAddress); + final int glerrPost = caller.glGetError(); // be safe, catch failure! + if(GL.GL_NO_ERROR != glerrPost) { + throw new GLException(String.format("GL-Error 0x%X while creating %s storage for buffer %d of size %d with data %s", + glerrPost, "mutable", bufferName, size, data)); + } + final GLBufferStorageImpl objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, 0 /* immutableFlags */); + final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, objNew); + if (DEBUG) { + System.err.printf("%s.%s direct: %d: %s -> %s%n", msgClazzName, msgCreateNamed, bufferName, objOld, objNew); + } + if( null != objOld ) { + objOld.setMappedBuffer(null); + } + } + + /** + * Must be called when deleting GL buffer objects vis <code>glDeleteBuffers</code>. + * @param count + * @param bufferNames + * @param offset + */ + public synchronized final void notifyBuffersDeleted(final int count, final int[] bufferNames, final int offset) { + for(int i=0; i<count; i++) { + notifyBufferDeleted(bufferNames[i+offset], i, count); + } + } + /** + * Must be called when deleting GL buffer objects vis <code>glDeleteBuffers</code>. + * @param n + * @param bufferNames + */ + public synchronized final void notifyBuffersDeleted(final int n, final IntBuffer bufferNames) { + final int offset = bufferNames.position(); + for(int i=0; i<n; i++) { + notifyBufferDeleted(bufferNames.get(i+offset), i, n); + } + } + /** + * Must be called when deleting GL buffer objects vis {@link GL#glDeleteBuffers(int, IntBuffer)}. + * @param bufferName + * @param i + * @param count + */ + private synchronized final void notifyBufferDeleted(final int bufferName, final int i, final int count) { + final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, null); + if (DEBUG) { + System.err.printf("%s.notifyBuffersDeleted()[%d/%d]: %d: %s -> null%n", msgClazzName, i+1, count, bufferName, objOld); + } + if( null == objOld ) { + if (DEBUG) { + System.err.printf("%s: %s.notifyBuffersDeleted()[%d/%d]: Buffer %d not tracked%n", warning, msgClazzName, i+1, count, bufferName); + Thread.dumpStack(); + } + return; + } + objOld.setMappedBuffer(null); + } + + public static interface MapBufferDispatch { + ByteBuffer allocNioByteBuffer(final long addr, final long length); + } + public static interface MapBufferRangeDispatch extends MapBufferDispatch { + long mapBuffer(final int targetOrBufferName, final long offset, final long length, final int access, final long glProcAddress); + } + public static interface MapBufferAllDispatch extends MapBufferDispatch { + long mapBuffer(final int targetOrBufferName, final int access, final long glProcAddress); + } + + private static final String GL_INVALID_OPERATION = "GL_INVALID_OPERATION"; + private static final String GL_INVALID_VALUE = "GL_INVALID_VALUE"; + + /** + * Must be called when mapping GL buffer objects via {@link GL#mapBuffer(int, int)}. + * @throws GLException if buffer is not bound to target + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + */ + public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker, + final GL caller, final int target, final int access, + final MapBufferAllDispatch dispatch, final long glProcAddress) throws GLException { + return this.mapBufferImpl(bufferStateTracker, caller, target, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress); + } + /** + * Must be called when mapping GL buffer objects via {@link GL#mapBufferRange(int, long, long, int)}. + * @throws GLException if buffer is not bound to target + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + * @throws GLException if buffer mapping range does not fit, incl. offset + */ + public synchronized final GLBufferStorage mapBuffer(final GLBufferStateTracker bufferStateTracker, + final GL caller, final int target, final long offset, final long length, final int access, + final MapBufferRangeDispatch dispatch, final long glProcAddress) throws GLException { + return this.mapBufferImpl(bufferStateTracker, caller, target, true /* useRange */, length, access, access, dispatch, glProcAddress); + } + /** + * Must be called when mapping GL buffer objects via {@link GL2#mapNamedBuffer(int, int)}. + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + */ + public synchronized final GLBufferStorage mapBuffer(final int bufferName, final int access, final MapBufferAllDispatch dispatch, + final long glProcAddress) throws GLException { + return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress); + } + /** + * Must be called when mapping GL buffer objects via {@link GL2#mapNamedBufferRange(int, long, long, int)}. + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + * @throws GLException if buffer mapping range does not fit, incl. offset + */ + public synchronized final GLBufferStorage mapBuffer(final int bufferName, final long offset, final long length, final int access, final MapBufferRangeDispatch dispatch, + final long glProcAddress) throws GLException { + return this.mapBufferImpl(0 /* target */, bufferName, true /* isNamedBuffer */, false /* useRange */, 0 /* offset */, 0 /* length */, access, dispatch, glProcAddress); + } + /** + * @throws GLException if buffer is not bound to target + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + * @throws GLException if buffer mapping range does not fit, incl. optional offset + */ + private synchronized final GLBufferStorage mapBufferImpl(final GLBufferStateTracker bufferStateTracker, + final GL caller, final int target, final boolean useRange, + long offset, long length, final int access, + final MapBufferDispatch dispatch, final long glProcAddress) throws GLException { + final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller); + if( 0 == bufferName ) { + throw new GLException(String.format("%s.%s: %s Buffer for target 0x%X not bound", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target)); + } + return this.mapBufferImpl(target, bufferName, false /* isNamedBuffer */, useRange, offset, length, access, dispatch, glProcAddress); + } + /** + * <p> + * A zero store size will avoid a native call and returns the unmapped {@link GLBufferStorage}. + * </p> + * <p> + * A null native mapping result indicating an error will + * not cause a GLException but returns the unmapped {@link GLBufferStorage}. + * This allows the user to handle this case. + * </p> + * @throws GLException if buffer is not tracked + * @throws GLException if buffer is already mapped + * @throws GLException if buffer has invalid store size, i.e. less-than zero + * @throws GLException if buffer mapping range does not fit, incl. optional offset + */ + private synchronized final GLBufferStorage mapBufferImpl(final int target, final int bufferName, final boolean isNamedBuffer, final boolean useRange, long offset, + long length, final int access, final MapBufferDispatch dispatch, + final long glProcAddress) throws GLException { + final GLBufferStorageImpl store = (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName); + if ( null == store ) { + throw new GLException("Buffer with name "+bufferName+" not tracked"); + } + if( null != store.getMappedBuffer() ) { + throw new GLException(String.format("%s.%s: %s Buffer storage of target 0x%X -> %d: %s is already mapped", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target, bufferName, store)); + } + final long storeSize = store.getSize(); + if ( 0 > storeSize ) { + throw new GLException(String.format("%s.%s: %s Buffer storage of target 0x%X -> %d: %s is of less-than zero", msgClazzName, msgMapBuffer, GL_INVALID_OPERATION, target, bufferName, store)); + } + if( !useRange ) { + length = storeSize; + offset = 0; + } + if( length + offset > storeSize ) { + throw new GLException(String.format("%s.%s: %s Out of range: offset %d, length %d, buffer storage of target 0x%X -> %d: %s", msgClazzName, msgMapBuffer, GL_INVALID_VALUE, offset, length, target, bufferName, store)); + } + if( 0 >= length || 0 > offset ) { + throw new GLException(String.format("%s.%s: %s Invalid values: offset %d, length %d, buffer storage of target 0x%X -> %d: %s", msgClazzName, msgMapBuffer, GL_INVALID_VALUE, offset, length, target, bufferName, store)); + } + if( 0 == storeSize ) { + return store; + } + final long addr; + if( isNamedBuffer ) { + if( useRange ) { + addr = ((MapBufferRangeDispatch)dispatch).mapBuffer(bufferName, offset, length, access, glProcAddress); + } else { + addr = ((MapBufferAllDispatch)dispatch).mapBuffer(bufferName, access, glProcAddress); + } + } else { + if( useRange ) { + addr = ((MapBufferRangeDispatch)dispatch).mapBuffer(target, offset, length, access, glProcAddress); + } else { + addr = ((MapBufferAllDispatch)dispatch).mapBuffer(target, access, glProcAddress); + } + } + // GL's map-buffer implementation always returns NULL on error, + // user shall validate the result and the corresponding getGLError() value! + if ( 0 == addr ) { + if( DEBUG ) { + System.err.printf("%s.%s: %s MapBuffer null result for target 0x%X -> %d: %s, off %d, len %d, acc 0x%X%n", msgClazzName, msgMapBuffer, warning, target, bufferName, store, offset, length, access); + Thread.dumpStack(); + } + // User shall handle the glError ! + } else { + final ByteBuffer buffer = dispatch.allocNioByteBuffer(addr, length); + Buffers.nativeOrder(buffer); + if( DEBUG ) { + System.err.printf("%s.%s: Target 0x%X -> %d: %s, off %d, len %d, acc 0x%X%n", msgClazzName, msgClazzName, target, bufferName, store.toString(false), offset, length, access); + } + store.setMappedBuffer(buffer); + } + return store; + } + + public static interface UnmapBufferDispatch { + boolean unmap(final int targetOrBufferName, final long glProcAddress); + } + + /** + * Must be called when unmapping GL buffer objects via {@link GL#glUnmapBuffer(int)}. + * <p> + * Only clear mapped buffer reference of {@link GLBufferStorage} + * if native unmapping was successful. + * </p> + */ + public synchronized final boolean unmapBuffer(final GLBufferStateTracker bufferStateTracker, final GL caller, + final int target, + final UnmapBufferDispatch dispatch, final long glProcAddress) { + final int bufferName = bufferStateTracker.getBoundBufferObject(target, caller); + final GLBufferStorageImpl store; + if( 0 == bufferName ) { + if (DEBUG) { + System.err.printf("%s: %s.%s: Buffer for target 0x%X not bound%n", warning, msgClazzName, msgUnmapped, target); + Thread.dumpStack(); + } + store = null; + } else { + store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName); + if( DEBUG && null == store ) { + System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName); + Thread.dumpStack(); + } + } + final boolean res = dispatch.unmap(target, glProcAddress); + if( res && null != store ) { + store.setMappedBuffer(null); + } + if( DEBUG ) { + System.err.printf("%s.%s %s target: 0x%X -> %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", target, bufferName, store.toString(false)); + if(!res) { + Thread.dumpStack(); + } + } + return res; + } + /** + * Must be called when unmapping GL buffer objects via {@link GL2#glUnmapNamedBufferEXT(int)}. + * <p> + * Only clear mapped buffer reference of {@link GLBufferStorage} + * if native unmapping was successful. + * </p> + */ + public synchronized final boolean unmapBuffer(final int bufferName, + final UnmapBufferDispatch dispatch, final long glProcAddress) { + final GLBufferStorageImpl store = (GLBufferStorageImpl) bufferName2StorageMap.get(bufferName); + if (DEBUG && null == store ) { + System.err.printf("%s: %s.%s: Buffer %d not tracked%n", warning, msgClazzName, msgUnmapped, bufferName); + Thread.dumpStack(); + } + final boolean res = dispatch.unmap(bufferName, glProcAddress); + if( res && null != store ) { + store.setMappedBuffer(null); + } + if (DEBUG) { + System.err.printf("%s.%s %s %d: %s%n", msgClazzName, msgUnmapped, res ? "OK" : "Failed", bufferName, store.toString(false)); + if(!res) { + Thread.dumpStack(); + } + } + return res; + } + + public synchronized final long getBufferSize(final int bufferName) { + final GLBufferStorageImpl store = (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName); + if ( null == store ) { + if (DEBUG) { + System.err.printf("%s: %s.getBufferSize(): Buffer %d not tracked%n", warning, msgClazzName, bufferName); + Thread.dumpStack(); + } + return 0; + } + return store.getSize(); + } + + public synchronized final GLBufferStorage getBufferStorage(final int bufferName) { + return (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName); + } + + /** + * Clear all tracked buffer object knowledge. + * <p> + * Shall only be called at GLContext destruction <i>iff</i> + * there are no other shared GLContext instances left. + * </p> + */ + public synchronized final void clear() { + if (DEBUG) { + System.err.printf("%s.clear() - Thread %s%n", msgClazzName, Thread.currentThread().getName()); + // Thread.dumpStack(); + } + bufferName2StorageMap.clear(); + } + + private static final String warning = "WARNING"; + private static final String msgClazzName = "GLBufferObjectTracker"; + private static final String msgUnmapped = "notifyBufferUnmapped()"; + private static final String msgCreateBound = "createBoundBufferStorage()"; + private static final String msgCreateNamed = "createNamedBufferStorage()"; + private static final String msgMapBuffer = "mapBuffer()"; +} diff --git a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java deleted file mode 100644 index b6d9b5682..000000000 --- a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 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: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution 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. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package jogamp.opengl; - -import javax.media.opengl.*; -import com.jogamp.common.util.IntLongHashMap; - -/** - * Tracks as closely as possible the sizes of allocated OpenGL buffer - * objects. - * <p> - * <code>glMapBuffer</code> or <code>glMapBufferRange</code> etc - * returns a <code>java.nio.ByteBuffer</code> - * instance reflecting the returned native address of respective calls - * and the actual buffer size. - * </p> - * <p> - * In case the buffer size is unknown, we need to compute this size by using - * <code>glGetBufferParameteriv</code> with a pname of <code>GL_BUFFER_SIZE</code>. - * The latter appears to be problematic due to the returned <code>int</code> value, - * where size should be of type <code>long</code>. - * Further more, this query appears to be costly for each glMapBuffer call - * at for Apple's new multithreaded OpenGL implementation. - * </p> - * <p> - * The buffer size state is shared across all shared OpenGL context, - * hence we share the GLBufferSizeTracker instance across all shared GLContexts. - * Hence utilizing this instance must be synchronized to be thread safe due to multithreading usage. - * </p> - * <p> - * We track the sizes of allocated buffer objects. - * We track calls to <code>glBindBuffer</code> etc to see which buffer is bound to - * which target and to <code>glBufferData</code> to see how large the buffer's - * allocated size is. When <code>glMapBuffer</code> is called, we consult our table - * of buffer sizes to see if we can return an answer without a glGet - * call. - * </p> - * <p> - * In the face of calls to glPushClientAttrib / glPopClientAttrib we currently punt - * and re-fetch the bound buffer object for the state in question; - * see, for example, <code>glVertexPointer</code> and the calls down to - * <code>GLBufferStateTracker.getBoundBufferObject()</code>. Note that we currently - * ignore new binding targets such as <code>GL_TRANSFORM_FEEDBACK_BUFFER_NV</code>; - * the fact that new binding targets may be added in the future makes - * it impossible to cache state for these new targets. - * </p> - * <p> - * Ignoring new binding targets, the primary situation in which we may - * not be able to return a cached answer is in the case of an error, - * where <code>glBindBuffer</code> may not have been called before trying to call - * <code>glBufferData</code>. Also, if external native code modifies a buffer - * object, we may return an incorrect answer. (FIXME: this case - * requires more thought, and perhaps stochastic and - * exponential-fallback checking. However, note that it can only occur - * in the face of external native code which requires that the - * application be signed anyway, so there is no security risk in this - * area.) - * </p> - */ -public class GLBufferSizeTracker { - protected static final boolean DEBUG; - - static { - Debug.initSingleton(); - DEBUG = Debug.isPropertyDefined("jogl.debug.GLBufferSizeTracker", true); - } - - // Map from buffer names to sizes. - // Note: should probably have some way of shrinking this map, but - // can't just make it a WeakHashMap because nobody holds on to the - // keys; would have to always track creation and deletion of buffer - // objects, which is probably sub-optimal. The expected usage - // pattern of buffer objects indicates that the fact that this map - // never shrinks is probably not that bad. - private final IntLongHashMap bufferSizeMap; - private final long sizeNotFount = 0xFFFFFFFFFFFFFFFFL; - - public GLBufferSizeTracker() { - bufferSizeMap = new IntLongHashMap(); - bufferSizeMap.setKeyNotFoundValue(sizeNotFount); - } - - public final void setBufferSize(GLBufferStateTracker bufferStateTracker, - int target, GL caller, long size) { - // Need to do some similar queries to getBufferSize below - int buffer = bufferStateTracker.getBoundBufferObject(target, caller); - if (buffer != 0) { - setDirectStateBufferSize(buffer, caller, size); - } - // We don't know the current buffer state. Note that the buffer - // state tracker will have made the appropriate OpenGL query if it - // didn't know what was going on, so at this point we have nothing - // left to do except drop this piece of information on the floor. - } - - public final void setDirectStateBufferSize(int buffer, GL caller, long size) { - bufferSizeMap.put(buffer, size); - } - - public final long getBufferSize(GLBufferStateTracker bufferStateTracker, - int target, - GL caller) { - // See whether we know what buffer is currently bound to the given - // state - final int buffer = bufferStateTracker.getBoundBufferObject(target, caller); - if (0 != buffer) { - return getBufferSizeImpl(target, buffer, caller); - } - // We don't know what's going on in this case; query the GL for an answer - // FIXME: both functions return 'int' types, which is not suitable, - // since buffer lenght is 64bit ? - int[] tmp = new int[1]; - caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); - if (DEBUG) { - System.err.println("GLBufferSizeTracker.getBufferSize(): no cached buffer information"); - } - return tmp[0]; - } - - public final long getDirectStateBufferSize(int buffer, GL caller) { - return getBufferSizeImpl(0, buffer, caller); - } - - private final long getBufferSizeImpl(int target, int buffer, GL caller) { - // See whether we know the size of this buffer object; at this - // point we almost certainly should if the application is - // written correctly - long sz = bufferSizeMap.get(buffer); - if (sizeNotFount == sz) { - // For robustness, try to query this value from the GL as we used to - // FIXME: both functions return 'int' types, which is not suitable, - // since buffer lenght is 64bit ? - int[] tmp = new int[1]; - if(0==target) { - // DirectState .. - if(caller.isFunctionAvailable("glGetNamedBufferParameterivEXT")) { - caller.getGL2().glGetNamedBufferParameterivEXT(buffer, GL.GL_BUFFER_SIZE, tmp, 0); - } else { - throw new GLException("Error: getDirectStateBufferSize called with unknown state and GL function 'glGetNamedBufferParameterivEXT' n/a to query size"); - } - } else { - caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); - } - if (tmp[0] == 0) { - // Assume something is wrong rather than silently going along - throw new GLException("Error: buffer size returned by "+ - ((0==target)?"glGetNamedBufferParameterivEXT":"glGetBufferParameteriv")+ - " was zero; probably application error"); - } - // Assume we just don't know what's happening - sz = tmp[0]; - bufferSizeMap.put(buffer, sz); - if (DEBUG) { - System.err.println("GLBufferSizeTracker.getBufferSize(): made slow query to cache size " + - sz + - " for buffer " + - buffer); - } - } - return sz; - } - - // This should be called on any major event where we might start - // producing wrong answers, such as OpenGL context creation and - // destruction if we don't know whether there are other currently- - // created contexts that might be keeping the buffer objects alive - // that we're dealing with - public final void clearCachedBufferSizes() { - bufferSizeMap.clear(); - } -} diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java index 304c8ec32..511c1b9b9 100644 --- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java +++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java @@ -102,14 +102,92 @@ public class GLBufferStateTracker { // Start with known unbound targets for known keys // setBoundBufferObject(GL2ES3.GL_VERTEX_ARRAY_BINDING, 0); // not using default VAO (removed in GL3 core) - only explicit setBoundBufferObject(GL.GL_ARRAY_BUFFER, 0); + setBoundBufferObject(GL4.GL_DRAW_INDIRECT_BUFFER, 0); setBoundBufferObject(GL.GL_ELEMENT_ARRAY_BUFFER, 0); setBoundBufferObject(GL2.GL_PIXEL_PACK_BUFFER, 0); setBoundBufferObject(GL2.GL_PIXEL_UNPACK_BUFFER, 0); - setBoundBufferObject(GL4.GL_DRAW_INDIRECT_BUFFER, 0); } - public final void setBoundBufferObject(int target, int value) { - bindingMap.put(target, value); + + /** + * GL_ARRAY_BUFFER, + * GL_ATOMIC_COUNTER_BUFFER, + * GL_COPY_READ_BUFFER, + * GL_COPY_WRITE_BUFFER, + * GL_DRAW_INDIRECT_BUFFER, + * GL_DISPATCH_INDIRECT_BUFFER, + * GL_ELEMENT_ARRAY_BUFFER, + * GL_PIXEL_PACK_BUFFER, + * GL_PIXEL_UNPACK_BUFFER, + * GL_SHADER_STORAGE_BUFFER, + * GL_TEXTURE_BUFFER, + * GL_TRANSFORM_FEEDBACK_BUFFER or + * GL_UNIFORM_BUFFER. + * + * GL_VERTEX_ARRAY_BINDING + * + */ + private static final int getQueryName(final int target) { + switch (target) { + case GL.GL_ARRAY_BUFFER: return GL.GL_ARRAY_BUFFER_BINDING; + case GL4.GL_ATOMIC_COUNTER_BUFFER: return GL4.GL_ATOMIC_COUNTER_BUFFER_BINDING; + case GL2ES3.GL_COPY_READ_BUFFER: return GL2ES3.GL_COPY_READ_BUFFER_BINDING; + case GL2ES3.GL_COPY_WRITE_BUFFER: return GL2ES3.GL_COPY_WRITE_BUFFER_BINDING; + case GL4.GL_DRAW_INDIRECT_BUFFER: return GL4.GL_DRAW_INDIRECT_BUFFER_BINDING; + case GL4.GL_DISPATCH_INDIRECT_BUFFER: return GL4.GL_DISPATCH_INDIRECT_BUFFER_BINDING; + case GL.GL_ELEMENT_ARRAY_BUFFER: return GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; + case GL2.GL_PIXEL_PACK_BUFFER: return GL2.GL_PIXEL_PACK_BUFFER_BINDING; + case GL2.GL_PIXEL_UNPACK_BUFFER: return GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; + // FIXME case GL4.GL_QUERY_BUFFER: return GL4.GL_QUERY_BUFFER_BINDING; + case GL4.GL_SHADER_STORAGE_BUFFER: return GL4.GL_SHADER_STORAGE_BUFFER_BINDING; + case GL2GL3.GL_TEXTURE_BUFFER: return GL2GL3.GL_TEXTURE_BINDING_BUFFER; + case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: return GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; + case GL2ES3.GL_UNIFORM_BUFFER: return GL2ES3.GL_UNIFORM_BUFFER_BINDING; + + case GL2ES3.GL_VERTEX_ARRAY_BINDING: return GL2ES3.GL_VERTEX_ARRAY_BINDING; + + default: + throw new GLException(String.format("GL_INVALID_ENUM: Invalid binding target 0x%X", target)); + } + } + private static final void checkTargetName(final int target) { + switch (target) { + case GL.GL_ARRAY_BUFFER: + case GL4.GL_ATOMIC_COUNTER_BUFFER: + case GL2ES3.GL_COPY_READ_BUFFER: + case GL2ES3.GL_COPY_WRITE_BUFFER: + case GL4.GL_DRAW_INDIRECT_BUFFER: + case GL4.GL_DISPATCH_INDIRECT_BUFFER: + case GL.GL_ELEMENT_ARRAY_BUFFER: + case GL2.GL_PIXEL_PACK_BUFFER: + case GL2.GL_PIXEL_UNPACK_BUFFER: + // FIXME case GL4.GL_QUERY_BUFFER: + case GL4.GL_SHADER_STORAGE_BUFFER: + case GL2GL3.GL_TEXTURE_BUFFER: + case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: + case GL2ES3.GL_UNIFORM_BUFFER: + + case GL2ES3.GL_VERTEX_ARRAY_BINDING: + return; + + default: + throw new GLException(String.format("GL_INVALID_ENUM: Invalid binding target 0x%X", target)); + } + } + + /** + * Must be called when binding a buffer, e.g.: + * <ul> + * <li><code>glBindBuffer</code></li> + * <li><code>glBindBufferBase</code></li> + * <li><code>glBindBufferRange</code></li> + * </ul> + * @param target + * @param bufferName + */ + public final void setBoundBufferObject(int target, int bufferName) { + checkTargetName(target); + final int oldBufferName = bindingMap.put(target, bufferName); /*** * Test for clearing bound buffer states when unbinding VAO, * Bug 692 Comment 5 is invalid, i.e. <https://jogamp.org/bugzilla/show_bug.cgi?id=692#c5>. @@ -117,8 +195,8 @@ public class GLBufferStateTracker { * after unbinding a VAO w/o unbinding the VBOs resulted to no visible image. * Leaving code in here for discussion - in case I am wrong. * - final int pre = bindingMap.put(target, value); - if( GL2ES3.GL_VERTEX_ARRAY_BINDING == target && keyNotFound != pre && 0 == value ) { + final int pre = bindingMap.put(target, bufferName); + if( GL2ES3.GL_VERTEX_ARRAY_BINDING == target && keyNotFound != pre && 0 == bufferName ) { // Unbinding a previous bound VAO leads to unbinding of all buffers! bindingMap.put(GL.GL_ARRAY_BUFFER, 0); bindingMap.put(GL.GL_ELEMENT_ARRAY_BUFFER, 0); @@ -127,38 +205,12 @@ public class GLBufferStateTracker { bindingMap.put(GL4.GL_DRAW_INDIRECT_BUFFER, 0); } */ if (DEBUG) { - System.err.println("GLBufferStateTracker.setBoundBufferObject() target 0x" + - Integer.toHexString(target) + " -> mapped bound buffer 0x" + - Integer.toHexString(value)); + System.err.println("GLBufferStateTracker.setBoundBufferObject() target " + + toHexString(target) + ": " + toHexString(oldBufferName) + " -> " + toHexString(bufferName)); // Thread.dumpStack(); } } - public static final int getQueryName(final int target) { - switch (target) { - case GL.GL_ARRAY_BUFFER: return GL.GL_ARRAY_BUFFER_BINDING; - case GL.GL_ELEMENT_ARRAY_BUFFER: return GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; - - case GL2ES3.GL_VERTEX_ARRAY_BINDING: return GL2ES3.GL_VERTEX_ARRAY_BINDING; - case GL2ES3.GL_COPY_READ_BUFFER: return GL2ES3.GL_COPY_READ_BUFFER_BINDING; - case GL2ES3.GL_COPY_WRITE_BUFFER: return GL2ES3.GL_COPY_WRITE_BUFFER_BINDING; - case GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER: return GL2ES3.GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; - case GL2ES3.GL_UNIFORM_BUFFER: return GL2ES3.GL_UNIFORM_BUFFER_BINDING; - - case GL2GL3.GL_TEXTURE_BUFFER: return GL2GL3.GL_TEXTURE_BINDING_BUFFER; - - case GL2.GL_PIXEL_PACK_BUFFER: return GL2.GL_PIXEL_PACK_BUFFER_BINDING; - case GL2.GL_PIXEL_UNPACK_BUFFER: return GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; - - case GL4.GL_DRAW_INDIRECT_BUFFER: return GL4.GL_DRAW_INDIRECT_BUFFER_BINDING; - case GL4.GL_ATOMIC_COUNTER_BUFFER: return GL4.GL_ATOMIC_COUNTER_BUFFER_BINDING; - case GL4.GL_DISPATCH_INDIRECT_BUFFER: return GL4.GL_DISPATCH_INDIRECT_BUFFER_BINDING; - case GL4.GL_SHADER_STORAGE_BUFFER: return GL4.GL_SHADER_STORAGE_BUFFER_BINDING; - // case GL4.GL_QUERY_BUFFER: return GL4.GL_QUERY_BUFFER_BINDING; - default: return 0; - } - } - /** Note: returns an unspecified value if the binding for the specified target (e.g. GL_ARRAY_BUFFER) is currently unknown. You must use isBoundBufferObjectKnown() to see whether the @@ -180,9 +232,9 @@ public class GLBufferStateTracker { value = 0; } if (DEBUG) { - System.err.println("GLBufferStateTracker.getBoundBufferObject() glerr[pre 0x"+Integer.toHexString(glerrPre)+", post 0x"+Integer.toHexString(glerrPost)+"], [queried value]: target 0x" + - Integer.toHexString(target) + " / query 0x"+Integer.toHexString(queryTarget)+ - " -> mapped bound buffer 0x" + Integer.toHexString(value)); + System.err.println("GLBufferStateTracker.getBoundBufferObject() glerr[pre "+toHexString(glerrPre)+", post "+toHexString(glerrPost)+"], [queried value]: target " + + toHexString(target) + " / query "+toHexString(queryTarget)+ + " -> mapped bound buffer " + toHexString(value)); } setBoundBufferObject(target, value); return value; @@ -204,11 +256,12 @@ public class GLBufferStateTracker { from GLContext.makeCurrent() in the future to possibly increase the robustness of these caches in the face of external native code manipulating OpenGL state. */ - public final void clearBufferObjectState() { + public final void clear() { + if (DEBUG) { + System.err.println("GLBufferStateTracker.clear() - Thread "+Thread.currentThread().getName()); + // Thread.dumpStack(); + } bindingMap.clear(); - if (DEBUG) { - System.err.println("GLBufferStateTracker.clearBufferObjectState()"); - //Thread.dumpStack(); - } } + private final String toHexString(int i) { return Integer.toHexString(i); } } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 66eed9d96..ee9f315c8 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -100,9 +100,9 @@ public abstract class GLContextImpl extends GLContext { private String glRendererLowerCase; private String glVersion; - // Tracks creation and initialization of buffer objects to avoid + // Tracks lifecycle of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations - private final GLBufferSizeTracker bufferSizeTracker; + private final GLBufferObjectTracker bufferObjectTracker; private final GLBufferStateTracker bufferStateTracker; private final GLStateTracker glStateTracker = new GLStateTracker(); private GLDebugMessageHandler glDebugHandler = null; @@ -141,10 +141,10 @@ public abstract class GLContextImpl extends GLContext { bufferStateTracker = new GLBufferStateTracker(); if ( null != shareWith ) { GLContextShareSet.registerSharing(this, shareWith); - bufferSizeTracker = ((GLContextImpl)shareWith).getBufferSizeTracker(); - assert (bufferSizeTracker != null) : "shared context hash null bufferSizeTracker: "+shareWith; + bufferObjectTracker = ((GLContextImpl)shareWith).getBufferObjectTracker(); + assert (bufferObjectTracker != null) : "shared context hash null GLBufferObjectTracker: "+shareWith; } else { - bufferSizeTracker = new GLBufferSizeTracker(); + bufferObjectTracker = new GLBufferObjectTracker(); } this.drawable = drawable; @@ -155,9 +155,9 @@ public abstract class GLContextImpl extends GLContext { private final void clearStates() { if( !GLContextShareSet.hasCreatedSharedLeft(this) ) { - bufferSizeTracker.clearCachedBufferSizes(); + bufferObjectTracker.clear(); } - bufferStateTracker.clearBufferObjectState(); + bufferStateTracker.clear(); glStateTracker.setEnabled(false); glStateTracker.clearStates(); } @@ -2122,8 +2122,8 @@ public abstract class GLContextImpl extends GLContext { //---------------------------------------------------------------------- // Helpers for buffer object optimizations - public final GLBufferSizeTracker getBufferSizeTracker() { - return bufferSizeTracker; + public final GLBufferObjectTracker getBufferObjectTracker() { + return bufferObjectTracker; } public final GLBufferStateTracker getBufferStateTracker() { diff --git a/src/jogl/classes/jogamp/opengl/MemoryObject.java b/src/jogl/classes/jogamp/opengl/MemoryObject.java index ac02e0bca..6ebefc517 100644 --- a/src/jogl/classes/jogamp/opengl/MemoryObject.java +++ b/src/jogl/classes/jogamp/opengl/MemoryObject.java @@ -31,17 +31,18 @@ package jogamp.opengl; import java.nio.ByteBuffer; import java.util.HashMap; +import javax.media.opengl.GLBufferStorage; + import com.jogamp.common.util.HashUtil; /** - * + * @deprecated No more used for GL buffer storage tracking, see {@link GLBufferStorage} and {@link GLBufferObjectTracker}. */ public class MemoryObject { private final long addr; private final long size; private final int hash; private ByteBuffer buffer=null; - public MemoryObject(long addr, long size) { this.addr = addr; this.size = size; diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java index c329945c4..458a9c94f 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java @@ -352,11 +352,11 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun @Override public void glVertexPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayBound()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayBound()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -373,7 +373,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } @Override public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } @@ -384,11 +384,11 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun @Override public void glColorPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayBound()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayBound()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -404,7 +404,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } @Override public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } @@ -418,11 +418,11 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun throw new GLException("Only 3 components per normal allowed"); } if(array.isVBO()) { - if(!gl.glIsVBOArrayBound()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayBound()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -438,7 +438,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } @Override public void glNormalPointer(int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } @@ -449,11 +449,11 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun @Override public void glTexCoordPointer(GLArrayData array) { if(array.isVBO()) { - if(!gl.glIsVBOArrayBound()) { + if(!gl.isVBOArrayBound()) { throw new GLException("VBO array is not enabled: "+array); } } else { - if(gl.glIsVBOArrayBound()) { + if(gl.isVBOArrayBound()) { throw new GLException("VBO array is not disabled: "+array); } Buffers.rangeCheck(array.getBuffer(), 1); @@ -470,7 +470,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun } @Override public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) { - int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + int vboName = gl.getBoundBuffer(GL.GL_ARRAY_BUFFER); if(vboName==0) { throw new GLException("no GL_ARRAY_BUFFER VBO bound"); } |