diff options
author | Sven Gothel <[email protected]> | 2014-01-14 07:37:26 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-01-14 07:37:26 +0100 |
commit | 7c5483d5b20aed9c87c5ce3f6bc840b6546edcd1 (patch) | |
tree | d991b71ce688d981eb14c1ef2174f2140b564467 | |
parent | 6c971f91fbe6a7e3bc45563d80d42a753586d629 (diff) |
Bug 942 - Share GLBufferStateTracker ; Unify GLBufferStateTracker and GLBufferSizeTracker (simplification)
Due to future mapped buffer tracking, the GLBufferStateTracker instance shall be shared
across shared GLContextImpl instances similar to GLSizeStateTracker!
This allows us to merge GLSizeStateTracker code into GLBufferStateTracker
to simplify the implementation.
+++
Clear the GLBufferStateTracker (@destruction) only if no more
created shares are left!
+++
-rw-r--r-- | make/config/jogl/gl-common.cfg | 2 | ||||
-rw-r--r-- | make/config/jogl/gl-gl4bc.cfg | 2 | ||||
-rw-r--r-- | make/config/jogl/gl-impl-CustomJavaCode-common.java | 6 | ||||
-rw-r--r-- | make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java | 3 | ||||
-rw-r--r-- | make/config/jogl/gl-impl-CustomJavaCode-gles1.java | 3 | ||||
-rw-r--r-- | make/config/jogl/gl-impl-CustomJavaCode-gles3.java | 3 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java | 200 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java | 195 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLContextImpl.java | 28 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/opengl/GLContextShareSet.java | 24 |
10 files changed, 192 insertions, 274 deletions
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg index b84115445..ee4af5e69 100644 --- a/make/config/jogl/gl-common.cfg +++ b/make/config/jogl/gl-common.cfg @@ -557,7 +557,7 @@ JavaEpilogue glPushClientAttrib bufferStateTracker.clearBufferObjectState(); JavaEpilogue glPushClientAttrib glStateTracker.pushAttrib(mask); JavaEpilogue glPopClientAttrib bufferStateTracker.clearBufferObjectState(); JavaEpilogue glPopClientAttrib glStateTracker.popAttrib(); -JavaEpilogue glBufferData bufferSizeTracker.setBufferSize(bufferStateTracker, {0}, this, {1}); +JavaEpilogue glBufferData bufferStateTracker.setBufferSize({0}, this, {1}); BufferObjectKind Array glColorPointer BufferObjectKind Array glEdgeFlagPointer diff --git a/make/config/jogl/gl-gl4bc.cfg b/make/config/jogl/gl-gl4bc.cfg index c3a392c52..e6e85e2e5 100644 --- a/make/config/jogl/gl-gl4bc.cfg +++ b/make/config/jogl/gl-gl4bc.cfg @@ -59,7 +59,7 @@ Include gl2_es2-CustomJavaCode.cfg # can only be computed by calling another routine ManuallyImplement glMapNamedBufferEXT ForceProcAddressGen glMapNamedBufferEXT -JavaEpilogue glNamedBufferDataEXT bufferSizeTracker.setDirectStateBufferSize({0}, this, {1}); +JavaEpilogue glNamedBufferDataEXT bufferStateTracker.setDirectStateBufferSize({0}, this, {1}); # Manuall implement glDebugMessageCallback* using the proc address resolver ForceProcAddressGen glDebugMessageCallback diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index b8da61065..3aeda1309 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -11,7 +11,7 @@ @Override public final long glGetBufferSize(int buffer) { - return bufferSizeTracker.getDirectStateBufferSize(buffer, this); + return bufferStateTracker.getDirectStateBufferSize(buffer, this); } @Override @@ -135,7 +135,7 @@ if (glProcAddress == 0) { throw new GLException("Method \""+(useRange?"glMapBufferRange":"glMapBuffer")+"\" not available"); } - final long sz = bufferSizeTracker.getBufferSize(bufferStateTracker, target, this); + final long sz = bufferStateTracker.getBufferSize(target, this); if (0 == sz) { return null; } @@ -188,7 +188,7 @@ if (glProcAddress == 0) { throw new GLException("Method \"glMapNamedBufferEXT\" not available"); } - final long sz = bufferSizeTracker.getDirectStateBufferSize(bufferName, this); + final long sz = bufferStateTracker.getDirectStateBufferSize(bufferName, this); if (0 == sz) { return null; } diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java index e7389de10..980603edc 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java @@ -18,11 +18,9 @@ public void setObjectTracker(GLObjectTracker tracker) { public GL4bcImpl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -280,7 +278,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; diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java index 8d5dcc7a5..1d1cf3abf 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java @@ -1,11 +1,9 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -199,7 +197,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; diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles3.java b/make/config/jogl/gl-impl-CustomJavaCode-gles3.java index d5ad16873..006ee4da1 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles3.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles3.java @@ -2,11 +2,9 @@ public GLES3Impl(GLProfile glp, GLContextImpl context) { this._context = context; if(null != context) { - this.bufferSizeTracker = context.getBufferSizeTracker(); this.bufferStateTracker = context.getBufferStateTracker(); this.glStateTracker = context.getGLStateTracker(); } else { - this.bufferSizeTracker = null; this.bufferStateTracker = null; this.glStateTracker = null; } @@ -211,7 +209,6 @@ public final GL2GL3 getGL2GL3() throws GLException { // private final boolean _isES3; -private final GLBufferSizeTracker bufferSizeTracker; private final GLBufferStateTracker bufferStateTracker; private final GLStateTracker glStateTracker; diff --git a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java deleted file mode 100644 index fa05902d5..000000000 --- a/src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java +++ /dev/null @@ -1,200 +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. When glMapBuffer or glMapBufferARB is called, in order to - * turn the resulting base address into a java.nio.ByteBuffer, we need - * to know the size in bytes of the allocated OpenGL buffer object. - * Previously we would compute this size by using - * glGetBufferParameterivARB with a pname of GL_BUFFER_SIZE, but - * it appears doing so each time glMapBuffer is called is too costly - * on at least Apple's new multithreaded OpenGL implementation. <P> - * - * Instead we now try to track the sizes of allocated buffer objects. - * We watch calls to glBindBuffer to see which buffer is bound to - * which target and to glBufferData to see how large the buffer's - * allocated size is. When glMapBuffer is called, we consult our table - * of buffer sizes to see if we can return an answer without a glGet - * call. <P> - * - * We share the GLBufferSizeTracker objects among all GLContexts for - * which sharing is enabled, because the namespace for buffer objects - * is the same for these contexts. <P> - * - * Tracking the state of which buffer objects are bound is done in the - * GLBufferStateTracker and is not completely trivial. 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, glVertexPointer and the calls down to - * GLBufferStateTracker.getBoundBufferObject(). Note that we currently - * ignore new binding targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV; - * the fact that new binding targets may be added in the future makes - * it impossible to cache state for these new targets. <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 glBindBuffer may not have been called before trying to call - * glBufferData. 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.) - */ - -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 keyNotFount = 0xFFFFFFFFFFFFFFFFL; - - public GLBufferSizeTracker() { - bufferSizeMap = new IntLongHashMap(); - bufferSizeMap.setKeyNotFoundValue(keyNotFount); - } - - 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 (keyNotFount == 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 16b7edca8..21b7da14d 100644 --- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java +++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java @@ -43,8 +43,11 @@ package jogamp.opengl; import javax.media.opengl.*; import com.jogamp.common.util.IntIntHashMap; +import com.jogamp.common.util.IntLongHashMap; /** + * <b>Buffer Target Mapping (Binding)</b> + * <p> * Tracks as closely as possible which OpenGL buffer object is bound * to which binding target in the current OpenGL context. * GLBufferStateTracker objects are allocated on a per-OpenGL-context basis. @@ -73,9 +76,52 @@ import com.jogamp.common.util.IntIntHashMap; * the binding state if glPushClientAttrib / glPopClientAttrib are * called, since we don't want the complexity of tracking stacks of * these attributes. + * </p> * + * <b>Buffer Size Mapping</b> + * <p> + * Tracks as closely as possible the sizes of allocated OpenGL buffer + * objects. When glMapBuffer or glMapBufferARB is called, in order to + * turn the resulting base address into a java.nio.ByteBuffer, we need + * to know the size in bytes of the allocated OpenGL buffer object. + * Previously we would compute this size by using + * glGetBufferParameterivARB with a pname of GL_BUFFER_SIZE, but + * it appears doing so each time glMapBuffer is called is too costly + * on at least Apple's new multithreaded OpenGL implementation. <P> + * + * Instead we now try to track the sizes of allocated buffer objects. + * We watch calls to glBindBuffer to see which buffer is bound to + * which target and to glBufferData to see how large the buffer's + * allocated size is. When glMapBuffer is called, we consult our table + * of buffer sizes to see if we can return an answer without a glGet + * call. <P> + * + * We share the GLBufferSizeTracker objects among all GLContexts for + * which sharing is enabled, because the namespace for buffer objects + * is the same for these contexts. <P> + * + * Tracking the state of which buffer objects are bound is done in the + * GLBufferStateTracker and is not completely trivial. 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, glVertexPointer and the calls down to + * GLBufferStateTracker.getBoundBufferObject(). Note that we currently + * ignore new binding targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV; + * the fact that new binding targets may be added in the future makes + * it impossible to cache state for these new targets. <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 glBindBuffer may not have been called before trying to call + * glBufferData. 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 GLBufferStateTracker { protected static final boolean DEBUG; @@ -89,14 +135,24 @@ public class GLBufferStateTracker { // known that no buffer is bound to the target, according to the // OpenGL specifications. // http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml - private final IntIntHashMap bindingMap; - private final int keyNotFound = 0xFFFFFFFF; + private final IntIntHashMap bufferBindingMap; + private final int bufferNotFound = 0xFFFFFFFF; + + // 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 sizeNotFound = 0xFFFFFFFFFFFFFFFFL; private final int[] bufTmp = new int[1]; public GLBufferStateTracker() { - bindingMap = new IntIntHashMap(); - bindingMap.setKeyNotFoundValue(keyNotFound); + bufferBindingMap = new IntIntHashMap(); + bufferBindingMap.setKeyNotFoundValue(bufferNotFound); // 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 @@ -105,10 +161,26 @@ public class GLBufferStateTracker { setBoundBufferObject(GL2.GL_PIXEL_PACK_BUFFER, 0); setBoundBufferObject(GL2.GL_PIXEL_UNPACK_BUFFER, 0); setBoundBufferObject(GL4.GL_DRAW_INDIRECT_BUFFER, 0); + + bufferSizeMap = new IntLongHashMap(); + bufferSizeMap.setKeyNotFoundValue(sizeNotFound); + } + + /** + * Clears all states, i.e. issues {@link #clearBufferObjectState()} + * and {@link #clearCachedBufferSizes()}. + */ + public final void clear() { + clearBufferObjectState(); + clearCachedBufferSizes(); } + // + // Buffer target mapping (binding) + // + public final void setBoundBufferObject(int target, int value) { - bindingMap.put(target, value); + bufferBindingMap.put(target, value); /*** * 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>. @@ -138,21 +210,21 @@ public class GLBufferStateTracker { You must use isBoundBufferObjectKnown() to see whether the return value is valid. */ public final int getBoundBufferObject(int target, GL caller) { - int value = bindingMap.get(target); - if (keyNotFound == value) { + int value = bufferBindingMap.get(target); + if (bufferNotFound == value) { // User probably either called glPushClientAttrib / // glPopClientAttrib or is querying an unknown target. See // whether we know how to fetch this state. boolean gotQueryTarget = true; - int queryTarget = 0; + int queryTarget; switch (target) { case GL2ES3.GL_VERTEX_ARRAY_BINDING: queryTarget = GL2ES3.GL_VERTEX_ARRAY_BINDING; break; - case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break; - case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break; - case GL2.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break; - case GL2.GL_PIXEL_UNPACK_BUFFER: queryTarget = GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; break; - case GL4.GL_DRAW_INDIRECT_BUFFER: queryTarget = GL4.GL_DRAW_INDIRECT_BUFFER_BINDING; break; - default: gotQueryTarget = false; break; + case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break; + case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break; + case GL2ES3.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break; + case GL2ES3.GL_PIXEL_UNPACK_BUFFER: queryTarget = GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; break; + case GL4.GL_DRAW_INDIRECT_BUFFER: queryTarget = GL4.GL_DRAW_INDIRECT_BUFFER_BINDING; break; + default: queryTarget = 0; gotQueryTarget = false; break; } if (gotQueryTarget) { final int glerrPre = caller.glGetError(); // clear @@ -189,10 +261,101 @@ public class GLBufferStateTracker { the robustness of these caches in the face of external native code manipulating OpenGL state. */ public final void clearBufferObjectState() { - bindingMap.clear(); + bufferBindingMap.clear(); if (DEBUG) { System.err.println("GLBufferStateTracker.clearBufferObjectState()"); //Thread.dumpStack(); } } + + // + // Buffer size mapping + // + + public final void setBufferSize(int target, GL caller, long size) { + // Need to do some similar queries to getBufferSize below + int buffer = 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(int target, GL caller) { + // See whether we know what buffer is currently bound to the given + // state + final int buffer = 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 (sizeNotFound == 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 length 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/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 8f1ba4585..8bbc82b5a 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -102,8 +102,7 @@ public abstract class GLContextImpl extends GLContext { // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations - private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet - private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); + private final GLBufferStateTracker bufferStateTracker; private final GLStateTracker glStateTracker = new GLStateTracker(); private GLDebugMessageHandler glDebugHandler = null; private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read } @@ -138,10 +137,13 @@ public abstract class GLContextImpl extends GLContext { public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) { super(); - if (shareWith != null) { + if ( null != shareWith ) { GLContextShareSet.registerSharing(this, shareWith); + bufferStateTracker = ((GLContextImpl)shareWith).getBufferStateTracker(); + assert (bufferStateTracker != null) : "shared context hash null bufferStateTracker: "+shareWith; + } else { + bufferStateTracker = new GLBufferStateTracker(); } - GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this); this.drawable = drawable; this.drawableRead = drawable; @@ -150,15 +152,9 @@ public abstract class GLContextImpl extends GLContext { } private final void clearStates() { - // Because we don't know how many other contexts we might be - // sharing with (and it seems too complicated to implement the - // GLObjectTracker's ref/unref scheme for the buffer-related - // optimizations), simply clear the cache of known buffers' sizes - // when we destroy contexts - if (bufferSizeTracker != null) { - bufferSizeTracker.clearCachedBufferSizes(); + if( !GLContextShareSet.hasCreatedSharedLeft(this) ) { + bufferStateTracker.clear(); } - bufferStateTracker.clearBufferObjectState(); glStateTracker.setEnabled(false); glStateTracker.clearStates(); } @@ -2123,14 +2119,6 @@ public abstract class GLContextImpl extends GLContext { //---------------------------------------------------------------------- // Helpers for buffer object optimizations - public final void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) { - this.bufferSizeTracker = bufferSizeTracker; - } - - public final GLBufferSizeTracker getBufferSizeTracker() { - return bufferSizeTracker; - } - public final GLBufferStateTracker getBufferStateTracker() { return bufferStateTracker; } diff --git a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java index 483767b44..c057c904c 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextShareSet.java +++ b/src/jogl/classes/jogamp/opengl/GLContextShareSet.java @@ -262,30 +262,6 @@ public class GLContextShareSet { return false; } - /** In order to avoid glGet calls for buffer object checks related - to glVertexPointer, etc. calls as well as glMapBuffer calls, we - need to share the same GLBufferSizeTracker object between - contexts sharing textures and display lists. For now we keep - this mechanism orthogonal to the GLObjectTracker to hopefully - keep things easier to understand. (The GLObjectTracker is - currently only needed in a fairly esoteric case, when the - Java2D/JOGL bridge is active, but the GLBufferSizeTracker - mechanism is now always required.) */ - public static void synchronizeBufferObjectSharing(final GLContext olderContextOrNull, final GLContext newContext) { - final GLContextImpl older = (GLContextImpl) olderContextOrNull; - final GLContextImpl newer = (GLContextImpl) newContext; - GLBufferSizeTracker tracker = null; - if (older != null) { - tracker = older.getBufferSizeTracker(); - assert (tracker != null) - : "registerForBufferObjectSharing was not called properly for the older context, or has a bug in it"; - } - if (tracker == null) { - tracker = new GLBufferSizeTracker(); - } - newer.setBufferSizeTracker(tracker); - } - //---------------------------------------------------------------------- // Internals only below this point |