diff options
author | Sven Gothel <[email protected]> | 2010-04-20 11:46:26 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-04-20 11:46:26 +0200 |
commit | 32790c376583beccd030eecd7c56cbe66d380172 (patch) | |
tree | 894613c7fc6a598aed59db87e5812ef6a44b83dd /src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java | |
parent | aa7084700bbf74d8bcc98cf0239f57cff2983423 (diff) |
JOGL GL4 preperation (cont):
- All available OpenGL versions (native/platform) are verified at GLProfile
initialization and can be queried ..
A mapping of major,compat -> major,minor,options is created.
- Removal of temp context creation, when creating a context.
This was necessary to query general availability of ARB_create_context.
Due to the shared context of X11GLXDrawableFactory and WindowsWGLDrawableFactory,
this is no more necessary.
Due to the version mapping, the ARB_create_context paramters are known.
- NativeWindow X11Lib: Added X11ErrorHandler, throwing a RuntimeException.
Necessary to catch BadMatch .. etc X11 errors, eg for glXCreateContextAttribsARB
Hence all X11 calls are covered now.
- X11DummyGLXDrawable needs to use an own Window, otherwise GLn n>2 fails
- Flattening the desktop GL* implementation,
all use GL4bcImpl, which reduces the footprint dramatically.
- GL*Impl.isGL*() (desktop) utilizes the GLContext.isGL*(),
hence the results reflect the actual native context version.
- GLContextImpl makeCurrent/create: Added workflow documentation,
clarified code, defined abstract methods to have a protocol.
- Removed moved files (from here to gluegen),
see gluegen a01cb3d59715a41153380f1977ec75263b762dc6
- NativeLibLoader -> <TYPE>JNILibLoader
- Fixed Exception Handling (as in gluegen bce53b52c8638729750c4286dbc04cb14329fd34),
ie removed empty catch Throwable ..
- GLContext.setSwapInterval(): Nop in offscreen case, otherwise X11IOError (NVIDIA Bug)
Test:
Tests
- Junit
- demos.gears.Gears
- demos.jrefract.JRefract
Platforms
- Linux 64/32 ATI/NVidia
- MacOsX
- Windows (virtualbox 3.1.6, offscreen failed)
TODO/BUGS:
- FIXME ATI GLn n>2 with AWT, can't make context current, works well on NVIDIA though
- FIXME GL3GL4: Due to GL3 and GL4 implementation bugs, we still choose GL2 first, if available!
- Add GL 3.3 to GL3/gl3ext.h
- Add GL 4.0 to GL3/gl3ext.h and fix the GL3/GL4 seperation
- Rename jogl.gl2.jar -> jogl.gldesktop.jar (as done with it's native lib already)
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java | 489 |
1 files changed, 315 insertions, 174 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index 8c5890d1e..3abb69a7f 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -45,9 +45,10 @@ import java.util.*; import javax.media.opengl.*; import javax.media.nativewindow.*; -import com.jogamp.nativewindow.impl.NWReflection; import com.jogamp.gluegen.runtime.*; import com.jogamp.gluegen.runtime.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.ReflectionUtil; public abstract class GLContextImpl extends GLContext { protected GLContextLock lock = new GLContextLock(); @@ -123,108 +124,137 @@ public abstract class GLContextImpl extends GLContext { return (GLDrawableImpl) getGLDrawable(); } - /** - * Platform dependent but harmonized implementation of the <code>ARB_create_context</code> - * mechanism to create a context.<br> - * The implementation shall verify this context, ie issue a - * <code>MakeCurrent</code> call if necessary.<br> - * - * @param share the shared context or null - * @param direct flag if direct is requested - * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below - * @param major major number - * @param minor minor number - * @return the valid context if successfull, or null - * - * @see #CTX_PROFILE_COMPAT - * @see #CTX_OPTION_FORWARD - * @see #CTX_OPTION_DEBUG - */ - protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, - int major, int minor); + public final GL getGL() { + return gl; + } - private long createContextARB(long share, boolean direct, int ctxOptionFlags, - int majorMax, int minorMax, - int majorMin, int minorMin, - int major[], int minor[]) { - major[0]=majorMax; - minor[0]=minorMax; - long _context=0; + public GL setGL(GL gl) { + if(DEBUG) { + String sgl1 = (null!=this.gl)?this.gl.getClass().toString()+", "+this.gl.toString():new String("<null>"); + String sgl2 = (null!=gl)?gl.getClass().toString()+", "+gl.toString():new String("<null>"); + Exception e = new Exception("setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread()+", "+sgl1+" -> "+sgl2); + e.printStackTrace(); + } + this.gl = gl; + return gl; + } - while ( 0==_context && - GLProfile.isValidGLVersion(major[0], minor[0]) && - ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) { + // This is only needed for Mac OS X on-screen contexts + protected void update() throws GLException { } - _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); + public boolean isSynchronized() { + return !lock.getFailFastMode(); + } - if(0==_context) { - if(!GLProfile.decrementGLVersion(major, minor)) break; - } + public void setSynchronized(boolean isSynchronized) { + lock.setFailFastMode(!isSynchronized); + } + + public abstract Object getPlatformGLExtensions(); + + public void release() throws GLException { + if (!lock.isHeld()) { + throw new GLException("Context not current on current thread"); + } + setCurrent(null); + try { + releaseImpl(); + } finally { + lock.unlock(); } - return _context; } - /** - * Platform independent part of using the <code>ARB_create_context</code> - * mechanism to create a context.<br> - */ - protected long createContextARB(long share, boolean direct, - int major[], int minor[], int ctp[]) - { - AbstractGraphicsConfiguration config = drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); - GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); - GLProfile glp = glCaps.getGLProfile(); - long _context = 0; + protected abstract void releaseImpl() throws GLException; - ctp[0] = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default - boolean isBackwardCompatibility = glp.isGL2() || glp.isGL3bc() || glp.isGL4bc() ; - int majorMin, minorMin; - int majorMax, minorMax; - if( glp.isGL4() ) { - // ?? majorMax=GLProfile.getMaxMajor(); minorMax=GLProfile.getMaxMinor(majorMax); - majorMax=4; minorMax=GLProfile.getMaxMinor(majorMax); - majorMin=4; minorMin=0; - } else if( glp.isGL3() ) { - majorMax=3; minorMax=GLProfile.getMaxMinor(majorMax); - majorMin=3; minorMin=1; - } else /* if( glp.isGL2() ) */ { - majorMax=3; minorMax=0; - majorMin=1; minorMin=1; // our minimum desktop OpenGL runtime requirements + public void destroy() { + if (lock.isHeld()) { + // release current context + release(); } - // Try the requested .. - if(isBackwardCompatibility) { - ctp[0] &= ~CTX_PROFILE_CORE ; - ctp[0] |= CTX_PROFILE_COMPAT ; - } - _context = createContextARB(share, direct, ctp[0], - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, - /* res */ major, minor); - - if(0==_context && !isBackwardCompatibility) { - ctp[0] &= ~CTX_PROFILE_COMPAT ; - ctp[0] |= CTX_PROFILE_CORE ; - ctp[0] &= ~CTX_OPTION_ANY ; - ctp[0] |= CTX_OPTION_FORWARD ; - _context = createContextARB(share, direct, ctp[0], - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, - /* res */ major, minor); - if(0==_context) { - // Try a compatible one .. even though not requested .. last resort - ctp[0] &= ~CTX_PROFILE_CORE ; - ctp[0] |= CTX_PROFILE_COMPAT ; - ctp[0] &= ~CTX_OPTION_FORWARD ; - ctp[0] |= CTX_OPTION_ANY ; - _context = createContextARB(share, direct, ctp[0], - /* max */ majorMax, minorMax, - /* min */ majorMin, minorMin, - /* res */ major, minor); - } + + // Must hold the lock around the destroy operation to make sure we + // don't destroy the context out from under another thread rendering to it + lock.lock(); + try { + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if (tracker != null) { + // Don't need to do anything for contexts that haven't been + // created yet + if (isCreated()) { + // If we are tracking creation and destruction of server-side + // OpenGL objects, we must decrement the reference count of the + // GLObjectTracker upon context destruction. + // + // Note that we can only eagerly delete these server-side + // objects if there is another context currrent right now + // which shares textures and display lists with this one. + tracker.unref(deletedObjectTracker); + } + } + */ + + // 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 (bufferStateTracker != null) { + bufferStateTracker.clearBufferObjectState(); + } + + if (glStateTracker != null) { + glStateTracker.clearStates(false); + } + + destroyImpl(); + } finally { + lock.unlock(); } - return _context; } + protected abstract void destroyImpl() throws GLException; + + //---------------------------------------------------------------------- + // + + /** + * MakeCurrent functionality, which also issues the creation of the actual OpenGL context.<br> + * The complete callgraph for general OpenGL context creation is:<br> + * <ul> + * <li> {@link #makeCurrent} <i>GLContextImpl</i> + * <li> {@link #makeCurrentImpl} <i>Platform Implementation</i> + * <li> {@link #create} <i>Platform Implementation</i> + * <li> If <code>ARB_create_context</code> is supported: + * <ul> + * <li> {@link #createContextARB} <i>GLContextImpl</i> + * <li> {@link #createContextARBImpl} <i>Platform Implementation</i> + * </ul> + * </ul><br> + * + * Once at startup, ie triggered by the singleton {@link GLDrawableImpl} constructor, + * calling {@link #createContextARB} will query all available OpenGL versions:<br> + * <ul> + * <li> <code>FOR ALL GL* DO</code>: + * <ul> + * <li> {@link #createContextARBMapVersionsAvailable} + * <ul> + * <li> {@link #createContextARBVersions} + * </ul> + * <li> {@link #mapVersionAvailable} + * </ul> + * </ul><br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #mapVersionAvailable + * @see #destroyContextARBImpl + */ public int makeCurrent() throws GLException { // Support calls to makeCurrent() over and over again with // different contexts without releasing them @@ -287,103 +317,206 @@ public abstract class GLContextImpl extends GLContext { return res; } + /** + * @see #makeCurrent + */ protected abstract int makeCurrentImpl() throws GLException; - public void release() throws GLException { - if (!lock.isHeld()) { - throw new GLException("Context not current on current thread"); - } - setCurrent(null); - try { - releaseImpl(); - } finally { - lock.unlock(); - } - } + /** + * @see #makeCurrent + */ + protected abstract void create() throws GLException ; - protected abstract void releaseImpl() throws GLException; + /** + * Platform dependent but harmonized implementation of the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * This method is called from {@link #createContextARB}.<br> + * + * The implementation shall verify this context with a + * <code>MakeContextCurrent</code> call.<br> + * + * @param share the shared context or null + * @param direct flag if direct is requested + * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below + * @param major major number + * @param minor minor number + * @return the valid context if successfull, or null + * + * @see #makeCurrent + * @see #CTX_PROFILE_COMPAT + * @see #CTX_OPTION_FORWARD + * @see #CTX_OPTION_DEBUG + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, + int major, int minor); - public void destroy() { - if (lock.isHeld()) { - // release current context - release(); - } + /** + * Destroy the context created by {@link #createContextARBImpl}. + * + * @see #makeCurrent + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract void destroyContextARBImpl(long context); - // Must hold the lock around the destroy operation to make sure we - // don't destroy the context out from under another thread rendering to it - lock.lock(); - try { - /* FIXME: refactor dependence on Java 2D / JOGL bridge - if (tracker != null) { - // Don't need to do anything for contexts that haven't been - // created yet - if (isCreated()) { - // If we are tracking creation and destruction of server-side - // OpenGL objects, we must decrement the reference count of the - // GLObjectTracker upon context destruction. - // - // Note that we can only eagerly delete these server-side - // objects if there is another context currrent right now - // which shares textures and display lists with this one. - tracker.unref(deletedObjectTracker); + /** + * Platform independent part of using the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * The implementation of {@link #create} shall use this protocol in case the platform supports <code>ARB_create_context</code>.<br> + * + * This method may call {@link #createContextARBImpl} and {@link #destroyContextARBImpl}. <br> + * + * This method will also query all available native OpenGL context when first called,<br> + * usually the first call should happen with the shared GLContext of the DrawableFactory.<br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected long createContextARB(long share, boolean direct, + int major[], int minor[], int ctp[]) + { + AbstractGraphicsConfiguration config = drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + GLProfile glp = glCaps.getGLProfile(); + long _context = 0; + + if( !mappedVersionsAvailableSet ) { + synchronized(mappedVersionsAvailableLock) { + if( !mappedVersionsAvailableSet ) { + createContextARBMapVersionsAvailable(4, false /* compat */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* compat */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + mappedVersionsAvailableSet=true; + } } - } - */ - - // 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 (bufferStateTracker != null) { - bufferStateTracker.clearBufferObjectState(); - } - - if (glStateTracker != null) { - glStateTracker.clearStates(false); - } - - destroyImpl(); - } finally { - lock.unlock(); + int reqMajor; + if(glp.isGL4()) { + reqMajor=4; + } else if (glp.isGL3()) { + reqMajor=3; + } else /* if (glp.isGL2()) */ { + reqMajor=2; } + boolean compat = glp.isGL2(); // incl GL3bc and GL4bc + + int key = compose8bit(reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, 0, 0); + int val = mappedVersionsAvailable.get( key ); + long _ctx = 0; + if(val>0) { + int _major = getComposed8bit(val, 1); + int _minor = getComposed8bit(val, 2); + int _ctp = getComposed8bit(val, 3); + + _ctx = createContextARBImpl(share, direct, _ctp, _major, _minor); + if(0!=_ctx) { + setGLFunctionAvailability(true, _major, _minor, _ctp); + } + } + return _ctx; } - protected abstract void destroyImpl() throws GLException; + private void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) + { + long _context; + int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default + if(compat) { + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + } - // This is only needed for Mac OS X on-screen contexts - protected void update() throws GLException { + // FIXME GL3GL4: + // To avoid OpenGL implementation bugs and raise compatibility + // within JOGL, we map to the proper GL version. + // This may change later when GL3 and GL4 drivers become more mature! + // Bug: To ensure GL profile compatibility within the JOGL application + // Bug: we always try to map against the highest GL version, + // Bug: so the use can always cast to a higher one + // Bug: int majorMax=GLContext.getMaxMajor(); + // Bug: int minorMax=GLContext.getMaxMinor(majorMax); + int majorMax, minorMax; + int majorMin, minorMin; + int major[] = new int[1]; + int minor[] = new int[1]; + if( 4 == reqMajor ) { + majorMax=4; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=4; minorMin=0; + } else if( 3 == reqMajor ) { + majorMax=3; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=3; minorMin=1; + } else /* if( glp.isGL2() ) */ { + majorMax=3; minorMax=0; + majorMin=1; minorMin=1; // our minimum desktop OpenGL runtime requirements + } + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + + if(0==_context && !compat) { + ctp &= ~CTX_PROFILE_COMPAT ; + ctp |= CTX_PROFILE_CORE ; + ctp &= ~CTX_OPTION_ANY ; + ctp |= CTX_OPTION_FORWARD ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + if(0==_context) { + // Try a compatible one .. even though not requested .. last resort + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + ctp &= ~CTX_OPTION_FORWARD ; + ctp |= CTX_OPTION_ANY ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + } + } + if(0!=_context) { + destroyContextARBImpl(_context); + mapVersionAvailable(reqMajor, compat, major[0], minor[0], ctp); + } } - public boolean isSynchronized() { - return !lock.getFailFastMode(); - } + private long createContextARBVersions(long share, boolean direct, int ctxOptionFlags, + int majorMax, int minorMax, + int majorMin, int minorMin, + int major[], int minor[]) { + major[0]=majorMax; + minor[0]=minorMax; + long _context=0; - public void setSynchronized(boolean isSynchronized) { - lock.setFailFastMode(!isSynchronized); - } + while ( 0==_context && + GLContext.isValidGLVersion(major[0], minor[0]) && + ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) { - public final GL getGL() { - return gl; - } + _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); - public GL setGL(GL gl) { - if(DEBUG) { - String sgl1 = (null!=this.gl)?this.gl.getClass().toString()+", "+this.gl.toString():new String("<null>"); - String sgl2 = (null!=gl)?gl.getClass().toString()+", "+gl.toString():new String("<null>"); - Exception e = new Exception("setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread()+", "+sgl1+" -> "+sgl2); - e.printStackTrace(); + if(0==_context) { + if(!GLContext.decrementGLVersion(major, minor)) break; + } } - this.gl = gl; - return gl; + return _context; } - public abstract Object getPlatformGLExtensions(); - //---------------------------------------------------------------------- // Managing the actual OpenGL version, usually figured at creation time. // As a last resort, the GL_VERSION string may be used .. @@ -395,7 +528,15 @@ public abstract class GLContextImpl extends GLContext { * Otherwise .. don't touch .. */ protected void setContextVersion(int major, int minor, int ctp) { + if (0==ctp) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } if(major>0 || minor>0) { + if (!GLContext.isValidGLVersion(major, minor)) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } ctxMajorVersion = major; ctxMinorVersion = minor; ctxOptions = ctp; @@ -408,6 +549,7 @@ public abstract class GLContextImpl extends GLContext { if(null==versionStr) { throw new GLException("GL_VERSION is NULL: "+this); } + ctxOptions = ctp; // Set version Version version = new Version(versionStr); @@ -460,7 +602,10 @@ public abstract class GLContextImpl extends GLContext { // private Object createInstance(GLProfile glp, String suffix, Class[] cstrArgTypes, Object[] cstrArgs) { - return NWReflection.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs); + try { + return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + return null; } /** Create the GL for this context. */ @@ -697,10 +842,6 @@ public abstract class GLContextImpl extends GLContext { return Thread.currentThread().getName(); } - public static String toHexString(long hex) { - return "0x" + Long.toHexString(hex); - } - //---------------------------------------------------------------------- // Helpers for buffer object optimizations |