diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java | 293 |
1 files changed, 195 insertions, 98 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index ca689ed81..6c15a2d92 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -41,20 +41,37 @@ package com.jogamp.opengl.impl; import com.jogamp.common.os.DynamicLookupHelper; -import java.nio.*; -import java.util.*; - -import javax.media.opengl.*; -import javax.media.nativewindow.*; -import com.jogamp.gluegen.runtime.*; -import com.jogamp.gluegen.runtime.opengl.*; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.gluegen.runtime.FunctionAddressResolver; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; public abstract class GLContextImpl extends GLContext { - protected GLContextLock lock = new GLContextLock(); protected static final boolean DEBUG = Debug.debug("GLContext"); protected static final boolean VERBOSE = Debug.verbose(); + protected GLContextLock lock = new GLContextLock(); + + /** + * Context full qualified name: display_type + display_connection + major + minor + ctp. + * This is the key for all cached ProcAddressTables, etc, to support multi display/device setups. + */ + protected String contextFQN; + // Cache of the functions that are available to be called at the current // moment in time protected ExtensionAvailabilityCache extensionAvailability; @@ -73,15 +90,25 @@ public abstract class GLContextImpl extends GLContext { protected GL gl; + protected static final Object mappedContextTypeObjectLock; + protected static final HashMap mappedExtensionAvailabilityCache; + protected static final HashMap mappedGLProcAddress; + protected static final HashMap mappedGLXProcAddress; + + static { + mappedContextTypeObjectLock = new Object(); + mappedExtensionAvailabilityCache = new HashMap(); + mappedGLProcAddress = new HashMap(); + mappedGLXProcAddress = new HashMap(); + } + public GLContextImpl(GLDrawableImpl drawable, GLDrawableImpl drawableRead, GLContext shareWith) { - extensionAvailability = new ExtensionAvailabilityCache(this); + super(); + if (shareWith != null) { GLContextShareSet.registerSharing(this, shareWith); } GLContextShareSet.registerForBufferObjectSharing(shareWith, this); - // This must occur after the above calls into the - // GLContextShareSet, which set up state needed by the GL object - setGL(createGL(drawable.getGLProfile())); this.drawable = drawable; setGLDrawableRead(drawableRead); @@ -91,6 +118,32 @@ public abstract class GLContextImpl extends GLContext { this(drawable, null, shareWith); } + protected void resetStates() { + // 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); + } + + extensionAvailability = null; + glProcAddressTable = null; + gl = null; + contextFQN = null; + + super.resetStates(); + } + public void setGLDrawableRead(GLDrawable read) { boolean lockHeld = lock.isHeld(); if(lockHeld) { @@ -185,24 +238,7 @@ public abstract class GLContextImpl extends GLContext { } } */ - - // 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); - } - if (contextHandle != 0) { int lockRes = drawable.lockSurface(); if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { @@ -220,6 +256,8 @@ public abstract class GLContextImpl extends GLContext { } finally { lock.unlock(); } + + resetStates(); } protected abstract void destroyImpl() throws GLException; @@ -364,6 +402,8 @@ public abstract class GLContextImpl extends GLContext { } boolean newCreated = false; if (!isCreated()) { + GLProfile.initProfiles( + getGLDrawable().getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice()); newCreated = createImpl(); // may throws exception if fails! if (DEBUG) { if(newCreated) { @@ -401,6 +441,8 @@ public abstract class GLContextImpl extends GLContext { * The implementation shall verify this context with a * <code>MakeContextCurrent</code> call.<br> * + * The implementation shall leave the context current.<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 @@ -444,6 +486,8 @@ public abstract class GLContextImpl extends GLContext { * 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> * + * The implementation makes the context current, if successful<br> + * * @see #makeCurrentImpl * @see #create * @see #createContextARB @@ -454,14 +498,16 @@ public abstract class GLContextImpl extends GLContext { int major[], int minor[], int ctp[]) { AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); GLProfile glp = glCaps.getGLProfile(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARB: mappedVersionsAvailableSet "+ mappedVersionsAvailableSet); + System.err.println(getThreadName() + ": !!! createContextARB: mappedVersionsAvailableSet("+device.getConnection()+"): "+ + GLContext.getAvailableGLVersionsSet(device)); } - mapGLVersions(); + mapGLVersions(device); int reqMajor; if(glp.isGL4()) { @@ -471,47 +517,44 @@ public abstract class GLContextImpl extends GLContext { } 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; - synchronized(mappedVersionsAvailableLock) { - val = mappedVersionsAvailable.get( key ); - } + int _major[] = { 0 }; + int _minor[] = { 0 }; + int _ctp[] = { 0 }; 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( GLContext.getAvailableGLVersion(device, reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, + _major, _minor, _ctp)) { + _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, _major, _minor, _ctp); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]); } } return _ctx; } - private void mapGLVersions() { - if (!mappedVersionsAvailableSet) { - synchronized (mappedVersionsAvailableLock) { - if (!mappedVersionsAvailableSet) { - createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 - createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc - createContextARBMapVersionsAvailable(3, false /* core */); // GL3 - createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc - createContextARBMapVersionsAvailable(4, false /* core */); // GL4 - mappedVersionsAvailableSet = true; - if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARB: SET mappedVersionsAvailableSet " + mappedVersionsAvailableSet); - } - } + private final void mapGLVersions(AbstractGraphicsDevice device) { + if ( !GLContext.getAvailableGLVersionsSet(device) ) { + synchronized (GLContext.deviceVersionAvailable) { + createContextARBMapVersionsAvailable(4, false /* core */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* core */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + GLContext.setAvailableGLVersionsSet(device); + } + } else { + if(DEBUG) { + System.err.println(getThreadName() + ": no mapping, all versions set "+device.getConnection()); } } } private final void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) { + resetStates(); + long _context; int reqProfile = compat ? CTX_PROFILE_COMPAT : CTX_PROFILE_CORE ; int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default @@ -570,11 +613,14 @@ public abstract class GLContextImpl extends GLContext { } } if(0!=_context) { - destroyContextARBImpl(_context); - mapVersionAvailable(reqMajor, reqProfile, major[0], minor[0], ctp); + AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, major[0], minor[0], ctp); setGLFunctionAvailability(true, major[0], minor[0], ctp); + destroyContextARBImpl(_context); + resetStates(); if (DEBUG) { - System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: "+getGLVersionAvailable(reqMajor, reqProfile)); + System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable HAVE: "+ + GLContext.getAvailableGLVersionAsString(device, reqMajor, reqProfile)); } } else if (DEBUG) { System.err.println(getThreadName() + ": !!! createContextARBMapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile); @@ -615,7 +661,7 @@ public abstract class GLContextImpl extends GLContext { * If major==0 && minor == 0 : Use GL_VERSION * Otherwise .. don't touch .. */ - protected final void setContextVersion(int major, int minor, int ctp) { + private final void setContextVersion(int major, int minor, int ctp) { if (0==ctp) { throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } @@ -643,6 +689,13 @@ public abstract class GLContextImpl extends GLContext { if (version.isValid()) { ctxMajorVersion = version.getMajor(); ctxMinorVersion = version.getMinor(); + // We cannot promote a non ARB context to >= 3.1, + // reduce it to 3.0 then. + if ( ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + && 0 == (ctxOptions & CTX_IS_ARB_CREATED) ) { + ctxMajorVersion = 3; + ctxMinorVersion = 0; + } ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); return; } @@ -750,13 +803,17 @@ public abstract class GLContextImpl extends GLContext { * the cache of which GL functions are available for calling through this * context. See {@link #isFunctionAvailable(String)} for more information on * the definition of "available". + * <br> + * All ProcaddressTables are being determined, the GL version is being set + * and the extension cache is determined as well. * * @param force force the setting, even if is already being set. - * This might be usefull if you change the OpenGL implementation. + * This might be useful if you change the OpenGL implementation. * * @see #setContextVersion */ - protected void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { + + protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { if(null!=this.gl && null!=glProcAddressTable && !force) { return; // already done and not forced } @@ -764,37 +821,34 @@ public abstract class GLContextImpl extends GLContext { setGL(createGL(getGLDrawable().getGLProfile())); } - updateGLProcAddressTable(major, minor, ctp); - } + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + contextFQN = getContextFQN(adevice, major, minor, ctp); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Context FQN: "+contextFQN); + } - /** - * Updates the cache of which GL functions are available for calling through this - * context. See {@link #isFunctionAvailable(String)} for more information on - * the definition of "available". - * - * @see #setContextVersion - */ - protected void updateGLProcAddressTable(int major, int minor, int ctp) { + updateGLXProcAddressTable(major, minor, ctp); + + // + // UpdateGLProcAddressTable functionality + // if(null==this.gl) { throw new GLException("setGLFunctionAvailability not called yet"); } - if (DEBUG) { - System.err.println(getThreadName() + ": !!! Initializing OpenGL extension address table for " + this); - } - int key = compose8bit(major, minor, ctp, 0); ProcAddressTable table = null; - synchronized(mappedProcAddressLock) { - table = (ProcAddressTable) mappedGLProcAddress.get( key ); + synchronized(mappedContextTypeObjectLock) { + table = (ProcAddressTable) mappedGLProcAddress.get( contextFQN ); if(null != table && !verifyInstance(gl.getGLProfile(), "ProcAddressTable", table)) { - throw new InternalError("GLContext GL ProcAddressTable mapped key("+major+","+minor+","+ctp+") -> "+ + throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+") -> "+ table.getClass().getName()+" not matching "+gl.getGLProfile().getGLImplBaseClassName()); } } if(null != table) { glProcAddressTable = table; if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable reusing key("+major+","+minor+","+ctp+") -> "+table.hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable reusing key("+contextFQN+") -> "+table.hashCode()); } } else { if (glProcAddressTable == null) { @@ -803,20 +857,52 @@ public abstract class GLContextImpl extends GLContext { new Object[] { new GLProcAddressResolver() } ); } resetProcAddressTable(getGLProcAddressTable()); - synchronized(mappedProcAddressLock) { - mappedGLProcAddress.put(key, getGLProcAddressTable()); + synchronized(mappedContextTypeObjectLock) { + mappedGLProcAddress.put(contextFQN, getGLProcAddressTable()); if(DEBUG) { - System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+major+","+minor+","+ctp+") -> "+getGLProcAddressTable().hashCode()); + System.err.println(getThreadName() + ": !!! GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+getGLProcAddressTable().hashCode()); } } } + + // + // Set GL Version + // setContextVersion(major, minor, ctp); - extensionAvailability.reset(); + // + // Update ExtensionAvailabilityCache + // + ExtensionAvailabilityCache eCache; + synchronized(mappedContextTypeObjectLock) { + eCache = (ExtensionAvailabilityCache) mappedExtensionAvailabilityCache.get( contextFQN ); + } + if(null != eCache) { + extensionAvailability = eCache; + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache reusing key("+contextFQN+") -> "+eCache.hashCode()); + } + } else { + if(null==extensionAvailability) { + extensionAvailability = new ExtensionAvailabilityCache(this); + } + extensionAvailability.reset(); + synchronized(mappedContextTypeObjectLock) { + mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+extensionAvailability.hashCode()); + } + } + } hasNativeES2Methods = isGLES2() || isExtensionAvailable("GL_ARB_ES2_compatibility") ; } + /** + * Updates the platform's 'GLX' function cache + */ + protected abstract void updateGLXProcAddressTable(int major, int minor, int ctp); + protected boolean hasNativeES2Methods = false; public final boolean hasNativeES2Methods() { return hasNativeES2Methods; } @@ -833,23 +919,26 @@ public abstract class GLContextImpl extends GLContext { * javax.media.opengl.GL#glPolygonOffset(float,float)} is available). */ public boolean isFunctionAvailable(String glFunctionName) { - if(isCreated()) { - // Check GL 1st (cached) - ProcAddressTable pTable = getGLProcAddressTable(); + // Check GL 1st (cached) + ProcAddressTable pTable = getGLProcAddressTable(); // null if ctx not created once + if(null!=pTable) { try { if(0!=pTable.getAddressFor(glFunctionName)) { return true; } } catch (Exception e) {} + } - // Check platform extensions 2nd (cached) - pTable = getPlatformExtProcAddressTable(); + // Check platform extensions 2nd (cached) - had to be enabled once + pTable = getPlatformExtProcAddressTable(); // null if ctx not created once + if(null!=pTable) { try { if(0!=pTable.getAddressFor(glFunctionName)) { return true; } } catch (Exception e) {} } + // dynamic function lookup at last incl name aliasing (not cached) DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper(); String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true); @@ -878,19 +967,31 @@ public abstract class GLContextImpl extends GLContext { * "GL_VERTEX_PROGRAM_ARB"). */ public boolean isExtensionAvailable(String glExtensionName) { - return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + if(null!=extensionAvailability) { + return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + return false; } public String getPlatformExtensionsString() { - return extensionAvailability.getPlatformExtensionsString(); + if(null!=extensionAvailability) { + return extensionAvailability.getPlatformExtensionsString(); + } + return null; } public String getGLExtensions() { - return extensionAvailability.getGLExtensions(); + if(null!=extensionAvailability) { + return extensionAvailability.getGLExtensions(); + } + return null; } public boolean isExtensionCacheInitialized() { - return extensionAvailability.isInitialized(); + if(null!=extensionAvailability) { + return extensionAvailability.isInitialized(); + } + return false; } /** Indicates which floating-point pbuffer implementation is in @@ -909,10 +1010,6 @@ public abstract class GLContextImpl extends GLContext { /** Only called for offscreen contexts; needed by glReadPixels */ public abstract int getOffscreenContextPixelDataType(); - protected static String getThreadName() { - return Thread.currentThread().getName(); - } - //---------------------------------------------------------------------- // Helpers for buffer object optimizations |