diff options
Diffstat (limited to 'src/net/java/games/jogl/impl/GLContextImpl.java')
-rwxr-xr-x | src/net/java/games/jogl/impl/GLContextImpl.java | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/src/net/java/games/jogl/impl/GLContextImpl.java b/src/net/java/games/jogl/impl/GLContextImpl.java new file mode 100755 index 000000000..26547c8c3 --- /dev/null +++ b/src/net/java/games/jogl/impl/GLContextImpl.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. 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 + * MIDROSYSTEMS, 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 net.java.games.jogl.impl; + +import java.awt.Component; + +import net.java.games.jogl.*; +import net.java.games.gluegen.runtime.*; + +public abstract class GLContextImpl extends GLContext { + protected GLContextLock lock = new GLContextLock(); + protected static final boolean DEBUG = Debug.debug("GLContextImpl"); + protected static final boolean VERBOSE = Debug.verbose(); + protected static final boolean NO_FREE = Debug.isPropertyDefined("jogl.GLContext.nofree"); + + static { + NativeLibLoader.load(); + } + + protected GLCapabilities capabilities; + protected GLCapabilitiesChooser chooser; + protected Component component; + + // Cache of the functions that are available to be called at the current + // moment in time + protected FunctionAvailabilityCache functionAvailability; + + protected GL gl; + protected GLU glu = new GLUImpl(gluProcAddressTable); + protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable(); + protected static boolean haveResetGLUProcAddressTable; + + public GLContextImpl(Component component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + GLContext shareWith) { + this.component = component; + this.capabilities = (GLCapabilities) capabilities.clone(); + this.chooser = chooser; + setGL(createGL()); + functionAvailability = new FunctionAvailabilityCache(this); + if (shareWith != null) { + GLContextShareSet.registerSharing(this, shareWith); + } + } + + public int makeCurrent() throws GLException { + lock.lock(); + int res = 0; + try { + res = makeCurrentImpl(); + } catch (GLException e) { + lock.unlock(); + throw(e); + } + if (res == CONTEXT_NOT_CURRENT) { + lock.unlock(); + } else { + setCurrent(this); + } + return res; + } + + 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(); + } + } + + protected abstract void releaseImpl() throws GLException; + + public void destroy() { + // Should we check the lock state? It should not be current on any + // thread. + destroyImpl(); + } + + protected abstract void destroyImpl() throws GLException; + + public boolean isSynchronized() { + return !lock.getFailFastMode(); + } + + public void setSynchronized(boolean isSynchronized) { + lock.setFailFastMode(!isSynchronized); + } + + public GL getGL() { + return gl; + } + + public void setGL(GL gl) { + this.gl = gl; + // Also reset the GL object for the pure-Java GLU implementation + ((GLUImpl) glu).setGL(gl); + } + + public GLU getGLU() { + return glu; + } + + public void setGLU(GLU glu) { + this.glu = glu; + } + + // Subclasses for onscreen GLContexts should override this to + // receive a notification from the GLCanvas or other implementation + // upon addNotify + public void setRealized() { + } + + //---------------------------------------------------------------------- + // Helpers for various context implementations + // + + // Flag for enabling / disabling automatic swapping of the front and + // back buffers + protected boolean autoSwapBuffers = true; + + // Offscreen context handling. Offscreen contexts should handle + // these resize requests in makeCurrent and clear the + // pendingOffscreenResize flag. + protected boolean pendingOffscreenResize; + protected int pendingOffscreenWidth; + protected int pendingOffscreenHeight; + + /** Create the GL for this context. */ + protected abstract GL createGL(); + + /** + * Pbuffer support; indicates whether this context is capable of + * creating a subordinate pbuffer context (distinct from an + * "offscreen context", which is typically software-rendered on all + * platforms). + */ + public abstract boolean canCreatePbufferContext(); + + /** + * Pbuffer support; creates a subordinate GLContext for a pbuffer + * associated with this context. + */ + public abstract GLContext createPbufferContext(GLCapabilities capabilities, + int initialWidth, + int initialHeight); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, binds this pbuffer to its texture target. + */ + public abstract void bindPbufferToTexture(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, releases this pbuffer from its texture target. + */ + public abstract void releasePbufferFromTexture(); + + /* + * Sets the swap interval for onscreen OpenGL contexts. Has no + * effect for offscreen contexts. + */ + public void setSwapInterval(final int interval) { + } + + /** Maps the given "platform-independent" function name to a real function + name. Currently this is only used to map "glAllocateMemoryNV" and + associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */ + protected abstract String mapToRealGLFunctionName(String glFunctionName); + + /** Maps the given "platform-independent" extension name to a real + function name. Currently this is only used to map + "GL_ARB_pbuffer" and "GL_ARB_pixel_format" to "WGL_ARB_pbuffer" + and "WGL_ARB_pixel_format" (not yet mapped to X11). */ + protected abstract String mapToRealGLExtensionName(String glExtensionName); + + public void setAutoSwapBufferMode(boolean autoSwapBuffers) { + this.autoSwapBuffers = autoSwapBuffers; + } + + public boolean getAutoSwapBufferMode() { + return autoSwapBuffers; + } + + /** Swaps the buffers of the OpenGL context if necessary. All error + conditions cause a GLException to be thrown. */ + public abstract void swapBuffers() throws GLException; + + /** Returns a non-null (but possibly empty) string containing the + space-separated list of available platform-dependent (e.g., WGL, + GLX) extensions. Can only be called while this context is + current. */ + public abstract String getPlatformExtensionsString(); + + /** Helper routine which resets a ProcAddressTable generated by the + GLEmitter by looking up anew all of its function pointers. */ + protected void resetProcAddressTable(Object table) { + Class tableClass = table.getClass(); + java.lang.reflect.Field[] fields = tableClass.getDeclaredFields(); + + for (int i = 0; i < fields.length; ++i) { + String addressFieldName = fields[i].getName(); + if (!addressFieldName.startsWith(ProcAddressHelper.PROCADDRESS_VAR_PREFIX)) { + // not a proc address variable + continue; + } + int startOfMethodName = ProcAddressHelper.PROCADDRESS_VAR_PREFIX.length(); + String glFuncName = addressFieldName.substring(startOfMethodName); + try { + java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName); + assert(addressField.getType() == Long.TYPE); + long newProcAddress = dynamicLookupFunction(glFuncName); + // set the current value of the proc address variable in the table object + addressField.setLong(table, newProcAddress); + if (DEBUG) { + // System.err.println(glFuncName + " = 0x" + Long.toHexString(newProcAddress)); + } + } catch (Exception e) { + throw new GLException("Cannot get GL proc address for method \"" + + glFuncName + "\": Couldn't set value of field \"" + addressFieldName + + "\" in class " + tableClass.getName(), e); + } + } + } + + /** Dynamically looks up the given function. */ + protected abstract long dynamicLookupFunction(String glFuncName); + + /** Indicates whether the underlying OpenGL context has been + created. This is used to manage sharing of display lists and + textures between contexts. */ + public abstract boolean isCreated(); + + /** + * Resets 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". + */ + protected void resetGLFunctionAvailability() { + // In order to be able to allow the user to uniformly install the + // debug and trace pipelines in their GLEventListener.init() + // method (for both GLCanvas and GLJPanel), we need to reset the + // actual GL object in the GLDrawable as well + setGL(createGL()); + + functionAvailability.flush(); + if (!haveResetGLUProcAddressTable) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing GLU extension address table"); + } + resetProcAddressTable(gluProcAddressTable); + haveResetGLUProcAddressTable = true; // Only need to do this once globally + } + } + + /** + * Returns true if the specified OpenGL core- or extension-function can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isFunctionAvailable(String)} for more details. + * + * @param glFunctionName the name of the OpenGL function (e.g., use + * "glPolygonOffsetEXT" to check if the {@link + * net.java.games.jogl.GL#glPolygonOffsetEXT(float,float)} is available). + */ + protected boolean isFunctionAvailable(String glFunctionName) { + return functionAvailability.isFunctionAvailable(mapToRealGLFunctionName(glFunctionName)); + } + + /** + * Returns true if the specified OpenGL extension can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isExtensionAvailable(String)} for more details. + * + * @param glExtensionName the name of the OpenGL extension (e.g., + * "GL_VERTEX_PROGRAM_ARB"). + */ + public boolean isExtensionAvailable(String glExtensionName) { + return functionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + + /** Indicates which floating-point pbuffer implementation is in + use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT, + or GLPbuffer.NV_FLOAT. */ + public int getFloatingPointMode() throws GLException { + throw new GLException("Not supported on non-pbuffer contexts"); + } + + /** Hook indicating whether the concrete GLContext implementation is + offscreen and therefore whether we need to process resize + requests. */ + protected abstract boolean isOffscreen(); + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. */ + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** Only called for offscreen contexts; needed by glReadPixels */ + public abstract int getOffscreenContextPixelDataType(); + + /** Routine needed only for offscreen contexts in order to resize + the underlying bitmap. Called by GLJPanel. */ + public void resizeOffscreenContext(int newWidth, int newHeight) { + if (!isOffscreen()) { + throw new GLException("Should only call for offscreen OpenGL contexts"); + } + pendingOffscreenResize = true; + pendingOffscreenWidth = newWidth; + pendingOffscreenHeight = newHeight; + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } +} |