aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games/jogl/impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games/jogl/impl')
-rw-r--r--src/net/java/games/jogl/impl/FunctionAvailabilityCache.java4
-rw-r--r--src/net/java/games/jogl/impl/GLContext.java764
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextImpl.java364
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextInitActionPair.java58
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextLock.java118
-rw-r--r--src/net/java/games/jogl/impl/GLContextShareSet.java4
-rwxr-xr-xsrc/net/java/games/jogl/impl/GLContextStack.java127
-rw-r--r--src/net/java/games/jogl/impl/GLDrawableHelper.java80
-rw-r--r--src/net/java/games/jogl/impl/GLPbufferImpl.java46
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java14
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java47
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/mipmap/BuildMipmap.java65
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java13
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java12
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java48
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java6
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContext.java22
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java16
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java46
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java10
22 files changed, 763 insertions, 1113 deletions
diff --git a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
index be5e26067..87f2b1819 100644
--- a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
+++ b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
@@ -54,7 +54,7 @@ import java.lang.reflect.*;
public final class FunctionAvailabilityCache {
private static final boolean DEBUG = Debug.debug("FunctionAvailabilityCache");
- FunctionAvailabilityCache(GLContext context)
+ FunctionAvailabilityCache(GLContextImpl context)
{
this.context = context;
}
@@ -243,7 +243,7 @@ public final class FunctionAvailabilityCache {
private HashMap availabilityCache = new HashMap(50);
private HashSet availableExtensionCache = new HashSet(50);
- private GLContext context;
+ private GLContextImpl context;
/**
* A class for storing and comparing revision version numbers.
diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java
deleted file mode 100644
index 41fa98c4b..000000000
--- a/src/net/java/games/jogl/impl/GLContext.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * 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
- * 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 net.java.games.jogl.impl;
-
-import java.awt.Component;
-import net.java.games.jogl.*;
-import net.java.games.gluegen.runtime.*;
-
-public abstract class GLContext {
- protected static final boolean DEBUG = Debug.debug("GLContext");
- protected static final boolean VERBOSE = Debug.verbose();
- protected static final boolean NO_FREE = Debug.isPropertyDefined("jogl.GLContext.nofree");
-
- static {
- NativeLibLoader.load();
- }
-
- protected Component component;
-
- // Indicates whether the component (if an onscreen context) has been
- // realized. Plausibly, before the component is realized the JAWT
- // should return an error or NULL object from some of its
- // operations; this appears to be the case on Win32 but is not true
- // at least with Sun's current X11 implementation (1.4.x), which
- // crashes with no other error reported if the DrawingSurfaceInfo is
- // fetched from a locked DrawingSurface during the validation as a
- // result of calling show() on the main thread. To work around this
- // we prevent any JAWT or OpenGL operations from being done until
- // addNotify() is called on the component.
- protected boolean realized;
-
- protected GLCapabilities capabilities;
- protected GLCapabilitiesChooser chooser;
- protected GL gl;
- protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable();
- protected static boolean haveResetGLUProcAddressTable;
- protected GLU glu = new GLUImpl(gluProcAddressTable);
- protected Thread renderingThread;
- protected Runnable deferredReshapeAction;
- // Support for OpenGL context destruction and recreation in the face
- // of the setRenderingThread optimization, which makes the context
- // permanently current on the animation thread. FIXME: should make
- // this more uniform and general, possibly by implementing in terms
- // of Runnables; however, necessary sequence of operations in
- // invokeGL makes this tricky.
- protected boolean deferredDestroy;
- protected boolean deferredSetRealized;
-
- // Error checking for setRenderingThread to ensure that one thread
- // doesn't attempt to call setRenderingThread on more than one
- // drawable
- protected static final ThreadLocal perThreadRenderingContext = new ThreadLocal();
-
- // This is a workaround for a bug in NVidia's drivers where
- // vertex_array_range is only safe for single-threaded use; a bug
- // has been filed, ID 80174. When an Animator is created for a
- // GLDrawable, the expectation is that the Animator will be started
- // shortly and that the user doesn't want rendering to occur from
- // the AWT thread. However, there is a small window between when the
- // Animator is created and attached to the GLDrawable and when it's
- // started (and sets the rendering thread) when repaint events can
- // be issued by the AWT thread if the component is realized. To work
- // around this problem, we currently specify in the Animator's API
- // that between the time it's created and started no redraws will
- // occur.
- protected volatile boolean willSetRenderingThread;
-
- // Flag for disabling all repaint and resize processing on the AWT
- // thread to avoid application-level deadlocks; only really used for
- // GLCanvas
- protected boolean noAutoRedraw;
-
- // 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;
-
- // Cache of the functions that are available to be called at the current
- // moment in time
- protected FunctionAvailabilityCache functionAvailability;
-
- // Support for recursive makeCurrent() calls as well as calling
- // other drawables' display() methods from within another one's
- protected static final ThreadLocal perThreadContextStack = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new GLContextStack();
- }
- };
- // This thread-local variable helps implement setRenderingThread()'s
- // optimized context handling. When the bottommost invokeGL() on the
- // execution stack finishes for the rendering thread for that
- // context, we pop the context off the context stack but do not free
- // it, instead storing it in this thread-local variable. This gives
- // us enough information to recover the context stack state in
- // subsequent invokeGL() calls.
- protected static final ThreadLocal perThreadSavedCurrentContext = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new GLContextInitActionPair(null, null);
- }
- };
-
- public GLContext(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);
- }
- }
-
- /** Runs the given runnable with this OpenGL context valid. */
- public synchronized void invokeGL(Runnable runnable, boolean isReshape, Runnable initAction) throws GLException {
- // Could be more clever about not calling this every time, but
- // Thread.currentThread() is very fast and this makes the logic simpler
- Thread currentThread = Thread.currentThread();
-
- // Defer JAWT and OpenGL operations until onscreen components are
- // realized
- if (!isRealized() ||
- willSetRenderingThread ||
- (renderingThread != null &&
- renderingThread != currentThread)) {
- // Support for removeNotify()/addNotify() when the
- // setRenderingThread optimization is in effect and before the
- // animation thread gets a chance to handle either request
- if (!isRealized() && deferredSetRealized) {
- setRealized();
- deferredSetRealized = false;
- } else {
- if (isReshape) {
- deferredReshapeAction = runnable;
- }
- return;
- }
- }
-
- if (isReshape && noAutoRedraw && !SingleThreadedWorkaround.doWorkaround()) {
- // Don't process reshape requests on the AWT thread
- deferredReshapeAction = runnable;
- return;
- }
-
- if (deferredDestroy) {
- deferredDestroy = false;
- if (renderingThread != null) {
- // Need to disable the setRenderingThread optimization to free
- // up the context
- setRenderingThread(null, initAction);
- }
- destroy();
- return;
- }
-
- // The goal of this code is to optimize OpenGL context handling as
- // much as possible. In particular:
- //
- // - setRenderingThread() works by making the "bottommost" OpenGL
- // context current once and not freeing it until the rendering
- // thread has been unset. Note that subsequent pushes of other
- // contexts will still necessarily cause them to be made current
- // and freed.
- //
- // - If the same context is pushed on the per-thread context stack
- // more than once back-to-back, the subsequent pushes will not
- // actually cause a makeCurrent/free to occur.
- //
- // Complexities occur because setRenderingThread() can be called
- // at any time. Currently we implement the rendering thread
- // optimization by popping it off the OpenGL context stack and
- // storing it in a thread-local variable.
-
- GLContextStack ctxStack = getPerThreadContextStack();
- GLContext savedPerThreadContext = getPerThreadSavedCurrentContext();
- Runnable savedPerThreadInitAction = getPerThreadSavedInitAction();
- setPerThreadSavedCurrentContext(null, null);
- if (ctxStack.size() == 0 &&
- savedPerThreadContext != null) {
- // The setRenderingThread optimization moved the current context
- // into thread-local storage. Put it back on the context stack,
- // because we might need to free it later.
- ctxStack.push(savedPerThreadContext, savedPerThreadInitAction);
- }
-
- GLContext curContext = ctxStack.peekContext();
- Runnable curInitAction = ctxStack.peekInitAction();
- boolean mustDoMakeCurrent = true;
-
- if (curContext == this) {
- mustDoMakeCurrent = false;
- }
-
- if (mustDoMakeCurrent) {
- if (curContext != null) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Freeing context " + curContext + " due to recursive makeCurrent");
- }
- curContext.free();
- }
-
- if (!makeCurrent(initAction)) {
- // Couldn't make the thread current because the component has not yet
- // been visualized, and therefore the context cannot be created.
- // We'll defer any actions until invokeGL() is called again at a time
- // when the component has been visualized.
- if (isReshape) {
- deferredReshapeAction = runnable;
- }
-
- // Clean up after ourselves on the way out.
- // NOTE that this is an abbreviated version of the code below
- // and should probably be refactored/cleaned up -- this bug
- // fix was done without a lot of intense thought about the
- // situation
- if (curContext != null) {
- curContext.makeCurrent(curInitAction);
- }
- return;
- }
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Making context " + this + " current");
- }
- }
- ctxStack.push(this, initAction);
-
- // At this point the OpenGL context is current. Offscreen contexts
- // handle resizing the backing bitmap in makeCurrent. Therefore we
- // may need to free and make the context current again if we
- // didn't actually make it current above.
- if (pendingOffscreenResize && renderingThread != null) {
- ctxStack.pop();
- free();
- if (!makeCurrent(initAction)) {
- throw new GLException("Error while resizing offscreen context");
- }
- ctxStack.push(this, initAction);
- }
-
- RuntimeException userException = null;
- GLException internalException = null;
-
- try {
- if (deferredReshapeAction != null) {
- deferredReshapeAction.run();
- deferredReshapeAction = null;
- }
- runnable.run();
- if (autoSwapBuffers && !isReshape) {
- swapBuffers();
- }
- } catch (RuntimeException e) {
- userException = e;
- throw(userException);
- } finally {
- if (userException != null) {
- // Disallow setRenderingThread if display action is throwing exceptions
- renderingThread = null;
- }
-
- boolean mustSkipFreeForRenderingThread = false;
- if (currentThread == renderingThread && curContext == null) {
- mustSkipFreeForRenderingThread = true;
- setPerThreadSavedCurrentContext(this, initAction);
- }
-
- // Always pop myself off the per-thread context stack
- ctxStack.pop();
-
- // Free the context unless the setRenderingThread optimization
- // kicks in.
- if (mustDoMakeCurrent && !mustSkipFreeForRenderingThread) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Freeing context " + this);
- }
-
- try {
- free();
- } catch (GLException e) {
- internalException = e;
- }
-
- if (curContext != null) {
- if (DEBUG && VERBOSE) {
- System.err.println(getThreadName() + ": Making context " + curContext + " current again");
- }
- try {
- curContext.makeCurrent(curInitAction);
- } catch (GLException e) {
- internalException = e;
- }
- }
- }
-
- // Check to see whether we pushed any remaining entry on the
- // per-thread context stack. If so, put it back in thread-local
- // storage unless the rendering thread optimization was recently
- // disabled.
- if (savedPerThreadContext != null) {
- assert(savedPerThreadContext == curContext);
- ctxStack.pop();
- if (savedPerThreadContext.getRenderingThread() == null) {
- try {
- savedPerThreadContext.free();
- } catch (GLException e) {
- internalException = e;
- }
- } else {
- setPerThreadSavedCurrentContext(savedPerThreadContext, savedPerThreadInitAction);
- }
- }
-
- // Make sure the end user's exception shows up in any stack
- // traces; the rethrow of the userException above should take
- // precedence if the internalException will otherwise squelch it
- if (internalException != null) {
- if (userException != null &&
- internalException.getCause() == null) {
- internalException.initCause(userException);
- throw(internalException);
- } else if (userException == null) {
- throw(internalException);
- }
- }
- }
- }
-
- 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;
- }
-
- /** Gives a hint to the context that setRenderingThread will be
- called in the near future; causes redraws to be halted. This is
- a workaround for bugs in NVidia's drivers and is used only by
- the Animator class. */
- public synchronized void willSetRenderingThread() {
- this.willSetRenderingThread = true;
- }
-
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- if (SingleThreadedWorkaround.doWorkaround()) {
- willSetRenderingThread = false;
- return;
- }
-
- Thread currentThread = Thread.currentThread();
- if (currentThreadOrNull != null && currentThreadOrNull != currentThread) {
- throw new GLException("Argument must be either the current thread or null");
- }
- if (renderingThread != null && currentThreadOrNull != null) {
- throw new GLException("Attempt to re-set or change rendering thread");
- }
- if (renderingThread == null && currentThreadOrNull == null) {
- throw new GLException("Attempt to clear rendering thread when already cleared");
- }
-
- Object currentThreadRenderingContext = perThreadRenderingContext.get();
- if (currentThreadOrNull != null &&
- currentThreadRenderingContext != null &&
- currentThreadRenderingContext != this) {
- throw new GLException("Attempt to call setRenderingThread on more than one drawable in this thread");
- }
-
- this.willSetRenderingThread = false;
- if (currentThreadOrNull == null) {
- renderingThread = null;
- perThreadRenderingContext.set(null);
- // Just in case the end user wasn't planning on drawing the
- // drawable even once more (which would give us a chance to free
- // the context), try to free the context now by performing an
- // invokeGL with a do-nothing action
- invokeGL(new Runnable() {
- public void run() {
- }
- }, false, initAction);
- } else {
- renderingThread = currentThreadOrNull;
- perThreadRenderingContext.set(this);
- }
- }
-
- public Thread getRenderingThread() {
- return renderingThread;
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraw) {
- this.noAutoRedraw = noAutoRedraw;
- }
-
- public boolean getNoAutoRedrawMode() {
- return noAutoRedraw;
- }
-
- 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;
-
- /** 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;
- }
-
- /** 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");
- }
-
- /** 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();
-
- /**
- * 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
- }
- recomputeSingleThreadedWorkaround();
- }
-
- /**
- * 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));
- }
-
- /**
- * 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);
-
- /** Create the GL for this context. */
- protected abstract GL createGL();
-
- /** Hook indicating whether the concrete GLContext implementation is
- offscreen and therefore whether we need to process resize
- requests. */
- protected abstract boolean isOffscreen();
-
- /** Only called for offscreen contexts; returns the buffer from
- which to read pixels (GL.GL_FRONT or GL.GL_BACK). */
- public abstract int getOffscreenContextReadBuffer();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextWidth();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextHeight();
-
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextPixelDataType();
-
- /** 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();
-
- /** Attempts to make the GL context current. If necessary, creates a
- context and calls the initAction once the context is current.
- Most error conditions cause an exception to be thrown, except
- for the case where the context can not be created because the
- component has not yet been visualized. In this case makeCurrent
- returns false and the caller should abort any OpenGL event
- processing and instead return immediately. */
- protected abstract boolean makeCurrent(Runnable initAction) throws GLException;
-
- /** Frees the OpenGL context. All error conditions cause a
- GLException to be thrown. */
- protected abstract void free() throws GLException;
-
- /** Inform the system that the associated heavyweight widget has
- been realized and that it is safe to create an associated OpenGL
- context. If the widget is later destroyed then destroy() should
- be called, which will cause the underlying OpenGL context to be
- destroyed as well as the realized bit to be set to false. */
- public void setRealized() {
- if (getRenderingThread() != null &&
- Thread.currentThread() != getRenderingThread()) {
- deferredSetRealized = true;
- return;
- }
- setRealized(true);
- }
-
- /** Sets only the "realized" bit. Should be called by subclasses
- from within the destroy() implementation. */
- protected synchronized void setRealized(boolean realized) {
- this.realized = realized;
- if (DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setRealized(" + realized + ") for context " + this);
- }
- }
-
- /** Indicates whether the component associated with this context has
- been realized. */
- public synchronized boolean getRealized() {
- return realized;
- }
-
- /** Destroys the underlying OpenGL context and changes the realized
- state to false. This should be called when the widget is being
- destroyed. */
- public synchronized void destroy() throws GLException {
- if (getRenderingThread() != null &&
- Thread.currentThread() != getRenderingThread()) {
- if (DEBUG) {
- System.err.println(getThreadName() + ": Deferred destroy for context " + this);
- }
- deferredDestroy = true;
- return;
- }
- setRealized(false);
- GLContextShareSet.contextDestroyed(this);
- destroyImpl();
- }
-
- /** Destroys the underlying OpenGL context. */
- protected abstract void destroyImpl() throws GLException;
-
- public synchronized boolean isRealized() {
- return (component == null || getRealized());
- }
-
- /** 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();
-
- /** Support for recursive makeCurrent() calls as well as calling
- other drawables' display() methods from within another one's */
- protected static GLContextStack getPerThreadContextStack() {
- return (GLContextStack) perThreadContextStack.get();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static GLContext getPerThreadSavedCurrentContext() {
- return ((GLContextInitActionPair) perThreadSavedCurrentContext.get()).getContext();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static Runnable getPerThreadSavedInitAction() {
- return ((GLContextInitActionPair) perThreadSavedCurrentContext.get()).getInitAction();
- }
-
- /** Support for setRenderingThread()'s optimized context handling */
- protected static void setPerThreadSavedCurrentContext(GLContext context, Runnable initAction) {
- perThreadSavedCurrentContext.set(new GLContextInitActionPair(context, initAction));
- }
-
- /** Support for automatic detection of whether we need to enable the
- single-threaded workaround for ATI and other vendors' cards.
- Should be called by subclasses for onscreen rendering inside
- their makeCurrent() implementation once the context is
- current. */
- private void recomputeSingleThreadedWorkaround() {
- GL gl = getGL();
- String str = gl.glGetString(GL.GL_VENDOR);
- if (str != null && str.indexOf("ATI") >= 0) {
- // Doing this instead of calling setRenderingThread(null) should
- // be OK since we are doing this very early in the maintenance
- // of the per-thread context stack, before we are actually
- // pushing any GLContext objects on it
- SingleThreadedWorkaround.shouldDoWorkaround();
- if( SingleThreadedWorkaround.doWorkaround() ) {
- renderingThread = null;
- }
- }
- }
-
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
-}
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();
+ }
+}
diff --git a/src/net/java/games/jogl/impl/GLContextInitActionPair.java b/src/net/java/games/jogl/impl/GLContextInitActionPair.java
deleted file mode 100755
index 379dda3ee..000000000
--- a/src/net/java/games/jogl/impl/GLContextInitActionPair.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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
- * 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 net.java.games.jogl.impl;
-
-public class GLContextInitActionPair {
- private GLContext ctx;
- private Runnable initAction;
-
- public GLContextInitActionPair(GLContext ctx, Runnable initAction) {
- this.ctx = ctx;
- this.initAction = initAction;
- }
-
- public GLContext getContext() {
- return ctx;
- }
-
- public Runnable getInitAction() {
- return initAction;
- }
-}
diff --git a/src/net/java/games/jogl/impl/GLContextLock.java b/src/net/java/games/jogl/impl/GLContextLock.java
new file mode 100755
index 000000000..7e40cbe46
--- /dev/null
+++ b/src/net/java/games/jogl/impl/GLContextLock.java
@@ -0,0 +1,118 @@
+/*
+ * 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 net.java.games.jogl.*;
+
+/** Implements the makeCurrent / release locking behavior of the
+ GLContext class. When "fail fast mode" is enabled, attempts to
+ lock the same GLContextLock on more than one thread cause
+ GLException to be raised. This lock is not recursive. Attempts to
+ lock it more than once on a given thread will cause GLException to
+ be raised. */
+
+public class GLContextLock {
+ private Object lock = new Object();
+ private Thread owner;
+ private boolean failFastMode = true;
+
+ /** Locks this GLContextLock on the current thread. If fail fast
+ mode is enabled and the GLContextLock is already owned by
+ another thread, throws GLException. */
+ public void lock() throws GLException {
+ synchronized(lock) {
+ Thread current = Thread.currentThread();
+ if (owner == null) {
+ owner = current;
+ } else if (owner != current) {
+ while (owner != null) {
+ if (failFastMode) {
+ throw new GLException("Attempt to make context current on thread " + current +
+ " which is already current on thread " + owner);
+ } else {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ throw new GLException(e);
+ }
+ }
+ }
+ owner = current;
+ } else {
+ throw new GLException("Attempt to make the same context current twice on thread " + current);
+ }
+ }
+ }
+
+ /** Unlocks this GLContextLock. */
+ public void unlock() throws GLException {
+ synchronized (lock) {
+ Thread current = Thread.currentThread();
+ if (owner == current) {
+ owner = null;
+ lock.notifyAll();
+ } else {
+ if (owner != null) {
+ throw new GLException("Attempt by thread " + current +
+ " to release context owned by thread " + owner);
+ } else {
+ throw new GLException("Attempt by thread " + current +
+ " to release unowned context");
+ }
+ }
+ }
+ }
+
+ /** Indicates whether this lock is held by the current thread. */
+ public boolean isHeld() {
+ synchronized(lock) {
+ Thread current = Thread.currentThread();
+ return (owner == current);
+ }
+ }
+
+ public void setFailFastMode(boolean onOrOff) {
+ failFastMode = onOrOff;
+ }
+
+ public boolean getFailFastMode() {
+ return failFastMode;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/GLContextShareSet.java b/src/net/java/games/jogl/impl/GLContextShareSet.java
index 60c6b7d59..f2e1c595a 100644
--- a/src/net/java/games/jogl/impl/GLContextShareSet.java
+++ b/src/net/java/games/jogl/impl/GLContextShareSet.java
@@ -41,6 +41,7 @@ package net.java.games.jogl.impl;
import java.lang.ref.*;
import java.util.*;
+import net.java.games.jogl.*;
/** Provides a mechanism by which OpenGL contexts can share textures
and display lists in the face of multithreading and asynchronous
@@ -61,7 +62,8 @@ public class GLContextShareSet {
public void add(GLContext ctx) {
if (allShares.put(ctx, dummyValue) == null) {
- if (ctx.isCreated()) {
+ // FIXME: downcast to GLContextImpl undesirable
+ if (((GLContextImpl) ctx).isCreated()) {
createdShares.put(ctx, dummyValue);
} else {
destroyedShares.put(ctx, dummyValue);
diff --git a/src/net/java/games/jogl/impl/GLContextStack.java b/src/net/java/games/jogl/impl/GLContextStack.java
deleted file mode 100755
index 089d53525..000000000
--- a/src/net/java/games/jogl/impl/GLContextStack.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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
- * 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 net.java.games.jogl.impl;
-
-import java.util.*;
-
-/** Implements a stack of GLContext objects along with the initActions
- that need to be run if their creation is necessary. This is used
- to detect redundant makeCurrent() calls and to allow one drawable
- to call display() of another from within the first drawable's
- display() method. */
-
-public class GLContextStack {
- private ArrayList data = new ArrayList();
-
- /** Pushes this GLContext on the stack. The passed context must be non-null. */
- public void push(GLContext ctx, Runnable initAction) {
- if (ctx == null) {
- throw new IllegalArgumentException("Null contexts are not allowed here");
- }
-
- data.add(new GLContextInitActionPair(ctx, initAction));
- }
-
- /** Removes and returns the top GLContext and associated
- initialization action, or null if there is none. */
- public GLContextInitActionPair pop() {
- if (data.size() == 0) {
- return null;
- }
-
- return (GLContextInitActionPair) data.remove(data.size() - 1);
- }
-
- /** Returns the top GLContext and associated initialization action
- without removing it, or null if there is none. */
- public GLContextInitActionPair peek() {
- return peek(0);
- }
-
- /** Returns the <i>i</i>th GLContext and associated initialization
- action from the top without removing it, or null if there is
- none. */
- public GLContextInitActionPair peek(int i) {
- if (data.size() - i <= 0) {
- return null;
- }
-
- return (GLContextInitActionPair) data.get(data.size() - i - 1);
- }
-
- /** Returns the top GLContext without removing it, or null if there
- is none. */
- public GLContext peekContext() {
- return peekContext(0);
- }
-
- /** Returns the <i>i</i>th GLContext from the top without removing
- it, or null if there is none. */
- public GLContext peekContext(int i) {
- GLContextInitActionPair pair = peek(i);
- if (pair == null) {
- return null;
- }
-
- return pair.getContext();
- }
-
- /** Returns the top initialization action without removing it, or
- null if there is none. */
- public Runnable peekInitAction() {
- return peekInitAction(0);
- }
-
- /** Returns the <i>i</i>th initialization action from the top
- without removing it, or null if there is none. */
- public Runnable peekInitAction(int i) {
- GLContextInitActionPair pair = peek(i);
- if (pair == null) {
- return null;
- }
-
- return pair.getInitAction();
- }
-
- /** Returns the number of entries on the GLContext stack. */
- public int size() {
- return data.size();
- }
-}
diff --git a/src/net/java/games/jogl/impl/GLDrawableHelper.java b/src/net/java/games/jogl/impl/GLDrawableHelper.java
index dd5d7c17f..da164088f 100644
--- a/src/net/java/games/jogl/impl/GLDrawableHelper.java
+++ b/src/net/java/games/jogl/impl/GLDrawableHelper.java
@@ -42,11 +42,13 @@ package net.java.games.jogl.impl;
import java.util.*;
import net.java.games.jogl.*;
-/** Encapsulates the implementation of most of the GLDrawable's
+/** Encapsulates the implementation of most of the GLAutoDrawable's
methods to be able to share it between GLCanvas and GLJPanel. */
public class GLDrawableHelper {
private volatile List listeners = new ArrayList();
+ private static final boolean DEBUG = Debug.debug("GLDrawableHelper");
+ private static final boolean VERBOSE = Debug.verbose();
public GLDrawableHelper() {
}
@@ -63,22 +65,92 @@ public class GLDrawableHelper {
listeners = newListeners;
}
- public void init(GLDrawable drawable) {
+ public void init(GLAutoDrawable drawable) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).init(drawable);
}
}
- public void display(GLDrawable drawable) {
+ public void display(GLAutoDrawable drawable) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).display(drawable);
}
}
- public void reshape(GLDrawable drawable,
+ public void reshape(GLAutoDrawable drawable,
int x, int y, int width, int height) {
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
((GLEventListener) iter.next()).reshape(drawable, x, y, width, height);
}
}
+
+ private static final ThreadLocal perThreadInitAction = new ThreadLocal();
+ private Runnable deferredReshapeAction;
+ /** Principal helper method which runs a Runnable with the context
+ made current. This could have been made part of GLContext, but a
+ desired goal is to be able to implement the GLCanvas in terms of
+ the GLContext's public APIs, and putting it into a separate
+ class helps ensure that we don't inadvertently use private
+ methods of the GLContext or its implementing classes. */
+ public void invokeGL(GLContext context,
+ Runnable runnable,
+ boolean isReshape,
+ Runnable initAction) {
+ // Support for recursive makeCurrent() calls as well as calling
+ // other drawables' display() methods from within another one's
+ GLContext lastContext = GLContext.getCurrent();
+ Runnable lastInitAction = (Runnable) perThreadInitAction.get();
+ if (lastContext != null) {
+ lastContext.release();
+ }
+
+ int res = 0;
+ try {
+ res = context.makeCurrent();
+ if (res == GLContext.CONTEXT_NOT_CURRENT) {
+ if (isReshape) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Deferring reshape action");
+ }
+ deferredReshapeAction = runnable;
+ }
+ } else {
+ if (res == GLContext.CONTEXT_CURRENT_NEW) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction");
+ }
+ initAction.run();
+ }
+ if (deferredReshapeAction != null) {
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running deferred reshape action");
+ }
+ Runnable act = deferredReshapeAction;
+ deferredReshapeAction = null;
+ act.run();
+ }
+ if (DEBUG && VERBOSE) {
+ System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running runnable");
+ }
+ runnable.run();
+ // FIXME: must phrase this in terms of new GLDrawable swap buffer functionality
+ if (((GLContextImpl) context).getAutoSwapBufferMode()) {
+ ((GLContextImpl) context).swapBuffers();
+ }
+ }
+ } finally {
+ try {
+ if (res != GLContext.CONTEXT_NOT_CURRENT) {
+ context.release();
+ }
+ } catch (Exception e) {
+ }
+ if (lastContext != null) {
+ int res2 = lastContext.makeCurrent();
+ if (res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
+ }
+ }
+ }
}
diff --git a/src/net/java/games/jogl/impl/GLPbufferImpl.java b/src/net/java/games/jogl/impl/GLPbufferImpl.java
index 7b17c3010..4e8bd7c63 100644
--- a/src/net/java/games/jogl/impl/GLPbufferImpl.java
+++ b/src/net/java/games/jogl/impl/GLPbufferImpl.java
@@ -53,13 +53,13 @@ import net.java.games.jogl.*;
public class GLPbufferImpl implements GLPbuffer {
// GLPbufferContext
- private GLContext context;
+ private GLContextImpl context;
private GLDrawableHelper drawableHelper = new GLDrawableHelper();
private boolean isInitialized=false;
private int floatMode;
public GLPbufferImpl(GLContext context) {
- this.context = context;
+ this.context = (GLContextImpl) context;
}
public void display() {
@@ -73,15 +73,12 @@ public class GLPbufferImpl implements GLPbuffer {
throw new GLException("Not yet implemented");
}
- public void setSize(Dimension d) {
- setSize(d.width, d.height);
- }
-
- public Dimension getSize() {
- return getSize(null);
+ public int getWidth() {
+ // FIXME
+ throw new GLException("Not yet implemented");
}
- public Dimension getSize(Dimension d) {
+ public int getHeight() {
// FIXME
throw new GLException("Not yet implemented");
}
@@ -110,26 +107,6 @@ public class GLPbufferImpl implements GLPbuffer {
context.setGLU(glu);
}
- void willSetRenderingThread() {
- // Not supported for pbuffers
- }
-
- public void setRenderingThread(Thread currentThreadOrNull) throws GLException {
- // Not supported for pbuffers
- }
-
- public Thread getRenderingThread() {
- // Not supported for pbuffers
- return null;
- }
-
- public void setNoAutoRedrawMode(boolean noAutoRedraws) {
- }
-
- public boolean getNoAutoRedrawMode() {
- return false;
- }
-
public void setAutoSwapBufferMode(boolean onOrOff) {
context.setAutoSwapBufferMode(onOrOff);
}
@@ -168,6 +145,11 @@ public class GLPbufferImpl implements GLPbuffer {
return context;
}
+ // FIXME: workaround for problems with deferring reshape actions
+ public GLDrawableHelper getDrawableHelper() {
+ return drawableHelper;
+ }
+
//----------------------------------------------------------------------
// No-ops for ComponentEvents
//
@@ -239,7 +221,7 @@ public class GLPbufferImpl implements GLPbuffer {
throw new GLException(e);
}
} else {
- context.invokeGL(invokeGLAction, isReshape, initAction);
+ drawableHelper.invokeGL(context, invokeGLAction, isReshape, initAction);
}
}
@@ -271,14 +253,14 @@ public class GLPbufferImpl implements GLPbuffer {
// being resized on the AWT event dispatch thread
class DisplayOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(displayAction, false, initAction);
+ drawableHelper.invokeGL(context, displayAction, false, initAction);
}
}
private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction =
new DisplayOnEventDispatchThreadAction();
class SwapBuffersOnEventDispatchThreadAction implements Runnable {
public void run() {
- context.invokeGL(swapBuffersAction, false, initAction);
+ drawableHelper.invokeGL(context, swapBuffersAction, false, initAction);
}
}
private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction =
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
index 8cc33f8ff..b921116db 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
@@ -45,7 +45,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class MacOSXGLContext extends GLContext
+public abstract class MacOSXGLContext extends GLContextImpl
{
private static JAWT jawt;
protected long nsContext; // NSOpenGLContext
@@ -119,7 +119,7 @@ public abstract class MacOSXGLContext extends GLContext
/**
* Creates and initializes an appropriate OpenGl nsContext. Should only be
- * called by {@link makeCurrent(Runnable)}.
+ * called by {@link makeCurrentImpl()}.
*/
protected boolean create(boolean pbuffer, boolean floatingPoint) {
MacOSXGLContext other = (MacOSXGLContext) GLContextShareSet.getShareContext(this);
@@ -165,7 +165,7 @@ public abstract class MacOSXGLContext extends GLContext
return true;
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (nsContext == 0) {
if (!create()) {
@@ -183,14 +183,12 @@ public abstract class MacOSXGLContext extends GLContext
if (created) {
resetGLFunctionAvailability();
- if (initAction != null) {
- initAction.run();
- }
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!CGL.clearCurrentContext(nsContext, nsView)) {
throw new GLException("Error freeing OpenGL nsContext");
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
index 37b2302c0..39aab5652 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOffscreenGLContext.java
@@ -83,7 +83,7 @@ public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (pendingOffscreenResize && (nsContext != 0)) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
destroyPBuffer();
@@ -93,9 +93,9 @@ public class MacOSXOffscreenGLContext extends MacOSXPbufferGLContext
pendingOffscreenResize = false;
}
}
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
index ba4eee0ef..f2398aab8 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXOnscreenGLContext.java
@@ -53,6 +53,18 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -82,8 +94,9 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
return true;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
MacOSXPbufferGLContext ctx = new MacOSXPbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
GLContextShareSet.registerSharing(this, ctx);
pbuffersToInstantiate.add(ctx);
return ctx;
@@ -97,22 +110,17 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
throw new GLException("Should not call this");
}
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- this.willSetRenderingThread = false;
- // FIXME: the JAWT in the Panther developer release
- // requires all JAWT operations to be done on the AWT
- // thread. This means that setRenderingThread won't work
- // yet on this platform. This method can be deleted once
- // the update for that release ships.
- }
-
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Assume the canvas might have been resized or moved and tell the OpenGL
// context to update itself. This used to be done only upon receiving a
// reshape event but that doesn't appear to be sufficient. An experiment
@@ -142,15 +150,20 @@ public class MacOSXOnscreenGLContext extends MacOSXGLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
if (!CGL.flushBuffer(nsContext, nsView)) {
throw new GLException("Error swapping buffers");
}
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
index 6c8004bee..b163bb9ce 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXPbufferGLContext.java
@@ -104,7 +104,7 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
created = false;
if (pBuffer == 0) {
@@ -112,10 +112,10 @@ public class MacOSXPbufferGLContext extends MacOSXGLContext {
System.err.println("Pbuffer not instantiated yet for " + this);
}
// pbuffer not instantiated yet
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean res = super.makeCurrent(initAction);
+ int res = super.makeCurrentImpl();
if (created) {
// Initialize render-to-texture support if requested
boolean rect = capabilities.getOffscreenRenderToTextureRectangle();
diff --git a/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java b/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
index 9c9c3122b..06a6a02bc 100644
--- a/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
+++ b/src/net/java/games/jogl/impl/mipmap/BuildMipmap.java
@@ -46,7 +46,8 @@ import java.io.*;
*/
public class BuildMipmap {
- private static boolean DEBUG = Debug.debug("BuildMipmap");
+ private static final boolean DEBUG = Debug.debug("BuildMipmap");
+ private static final boolean VERBOSE = Debug.verbose();
/** Creates a new instance of BuildMipmap */
public BuildMipmap() {
@@ -663,16 +664,18 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
if (DEBUG) {
System.err.println("GL Error(" + level + "): " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( srcImage );
- srcImage.clear();
- fos.close();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( srcImage );
+ srcImage.clear();
+ fos.close();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
@@ -769,15 +772,17 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage );
if (DEBUG) {
System.err.println("GL Error(" + level + "): " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( srcImage );
- srcImage.clear();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( srcImage );
+ srcImage.clear();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
@@ -817,15 +822,17 @@ public class BuildMipmap {
gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, newMipmapImage );
if (DEBUG) {
System.err.println("GL Error: " + gl.glGetError() );
- try {
- File file = new File( "glu2DMipmapJ" + level + ".bin" );
- FileOutputStream fos = new FileOutputStream( file );
- srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
- fos.getChannel().write( newMipmapImage );
- srcImage.clear();
- } catch( IOException e ) {
- System.err.println("IOException");
- System.err.println(e.getMessage());
+ if (VERBOSE) {
+ try {
+ File file = new File( "glu2DMipmapJ" + level + ".bin" );
+ FileOutputStream fos = new FileOutputStream( file );
+ srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) );
+ fos.getChannel().write( newMipmapImage );
+ srcImage.clear();
+ } catch( IOException e ) {
+ System.err.println("IOException");
+ System.err.println(e.getMessage());
+ }
}
}
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index e938c8023..338b11e6a 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -48,7 +48,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class WindowsGLContext extends GLContext {
+public abstract class WindowsGLContext extends GLContextImpl {
private static JAWT jawt;
protected long hglrc;
protected long hdc;
@@ -124,11 +124,11 @@ public abstract class WindowsGLContext extends GLContext {
/**
* Creates and initializes an appropriate OpenGL context. Should only be
- * called by {@link #makeCurrent(Runnable)}.
+ * called by {@link #makeCurrentImpl()}.
*/
protected abstract void create();
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (hglrc == 0) {
create();
@@ -177,13 +177,12 @@ public abstract class WindowsGLContext extends GLContext {
}
}
GLContextShareSet.contextCreated(this);
-
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!NO_FREE) {
if (!WGL.wglMakeCurrent(0, 0)) {
throw new GLException("Error freeing OpenGL context: " + WGL.GetLastError());
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
index c70607da7..d944a8684 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
@@ -92,9 +92,9 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
return false;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -106,7 +106,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (pendingOffscreenResize) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
if (hglrc != 0) {
@@ -117,7 +117,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
pendingOffscreenResize = false;
}
}
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
protected void destroyImpl() {
@@ -133,7 +133,7 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
}
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
protected void create() {
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
index 0dc1818fb..d4af4b3b7 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -51,6 +51,18 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
JAWT_DrawingSurfaceInfo dsi;
JAWT_Win32DrawingSurfaceInfo win32dsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -61,6 +73,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
super(component, capabilities, chooser, shareWith);
}
+ /*
public void invokeGL(Runnable runnable, boolean isReshape, Runnable initAction) throws GLException {
// Unfortunately, invokeGL can be called with the AWT tree lock
// held, and the Windows onscreen implementation of
@@ -79,6 +92,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
super.invokeGL(runnable, isReshape, initAction);
}
}
+ */
protected GL createGL()
{
@@ -101,10 +115,11 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
return haveWGLARBPbuffer();
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
WindowsPbufferGLContext ctx = new WindowsPbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
pbuffersToInstantiate.add(ctx);
return ctx;
}
@@ -117,13 +132,21 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ public void setRealized() {
+ realized = true;
+ }
+
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
WindowsPbufferGLContext ctx =
@@ -142,15 +165,20 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
if (!WGL.SwapBuffers(hdc) && (WGL.GetLastError() != 0)) {
throw new GLException("Error swapping buffers");
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index 26108a5cd..d58d15d02 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -382,7 +382,7 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
created = false;
if (buffer == 0) {
@@ -390,10 +390,10 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
if (DEBUG) {
System.err.println("pbuffer not instantiated yet");
}
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean res = super.makeCurrent(initAction);
+ int res = super.makeCurrentImpl();
if (DEBUG) {
System.err.println("super.makeCurrent() = " + res + ", created = " + created);
}
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java
index 837b7b791..7077c855e 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java
@@ -46,7 +46,7 @@ import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
-public abstract class X11GLContext extends GLContext {
+public abstract class X11GLContext extends GLContextImpl {
protected long display;
protected long drawable;
protected long visualID;
@@ -126,19 +126,9 @@ public abstract class X11GLContext extends GLContext {
public abstract boolean offscreenImageNeedsVerticalFlip();
- public synchronized void setRenderingThread(Thread currentThreadOrNull, Runnable initAction) {
- this.willSetRenderingThread = false;
- // FIXME: the JAWT on X11 grabs the AWT lock while the
- // DrawingSurface is locked, which means that no other events can
- // be processed. Currently we handle this by preventing the
- // effects of setRenderingThread. We should figure out a better
- // solution that is reasonably robust. Must file a bug to be fixed
- // in the 1.5 JAWT.
- }
-
/**
* Creates and initializes an appropriate OpenGl context. Should only be
- * called by {@link makeCurrent(Runnable)}.
+ * called by {@link makeCurrentImpl()}.
*/
protected abstract void create();
@@ -150,7 +140,7 @@ public abstract class X11GLContext extends GLContext {
return super.isExtensionAvailable(glExtensionName);
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
boolean created = false;
if (context == 0) {
create();
@@ -172,12 +162,12 @@ public abstract class X11GLContext extends GLContext {
if (created) {
resetGLFunctionAvailability();
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
if (!GLX.glXMakeCurrent(display, 0, 0)) {
throw new GLException("Error freeing OpenGL context");
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
index 2e30e2b18..c493d3380 100644
--- a/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OffscreenGLContext.java
@@ -95,9 +95,9 @@ public class X11OffscreenGLContext extends X11GLContext {
return false;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
throw new GLException("Not supported");
}
@@ -109,7 +109,7 @@ public class X11OffscreenGLContext extends X11GLContext {
throw new GLException("Should not call this");
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
display = X11GLContextFactory.getDisplayConnection();
if (pendingOffscreenResize) {
if (pendingOffscreenWidth != width || pendingOffscreenHeight != height) {
@@ -122,15 +122,15 @@ public class X11OffscreenGLContext extends X11GLContext {
}
}
mostRecentDisplay = display;
- return super.makeCurrent(initAction);
+ return super.makeCurrentImpl();
}
- public synchronized void swapBuffers() throws GLException {
+ public void swapBuffers() throws GLException {
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
display = 0;
}
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
index 2fd340d79..5a6fe23bb 100644
--- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
@@ -51,6 +51,18 @@ public class X11OnscreenGLContext extends X11GLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
+ // Indicates whether the component (if an onscreen context) has been
+ // realized. Plausibly, before the component is realized the JAWT
+ // should return an error or NULL object from some of its
+ // operations; this appears to be the case on Win32 but is not true
+ // at least with Sun's current X11 implementation (1.4.x), which
+ // crashes with no other error reported if the DrawingSurfaceInfo is
+ // fetched from a locked DrawingSurface during the validation as a
+ // result of calling show() on the main thread. To work around this
+ // we prevent any JAWT or OpenGL operations from being done until
+ // addNotify() is called on the component.
+ protected boolean realized;
+
// Variables for pbuffer support
List pbuffersToInstantiate = new ArrayList();
@@ -83,10 +95,11 @@ public class X11OnscreenGLContext extends X11GLContext {
return true;
}
- public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
- int initialWidth,
- int initialHeight) {
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
X11PbufferGLContext ctx = new X11PbufferGLContext(capabilities, initialWidth, initialHeight);
+ ctx.setSynchronized(true);
pbuffersToInstantiate.add(ctx);
return ctx;
}
@@ -106,13 +119,21 @@ public class X11OnscreenGLContext extends X11GLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ public void setRealized() {
+ realized = true;
+ }
+
+ protected int makeCurrentImpl() throws GLException {
try {
+ if (!realized) {
+ return CONTEXT_NOT_CURRENT;
+ }
if (!lockSurface()) {
- return false;
+ return CONTEXT_NOT_CURRENT;
}
- boolean ret = super.makeCurrent(initAction);
- if (ret) {
+ int ret = super.makeCurrentImpl();
+ if ((ret == CONTEXT_CURRENT) ||
+ (ret == CONTEXT_CURRENT_NEW)) {
// Instantiate any pending pbuffers
while (!pbuffersToInstantiate.isEmpty()) {
X11PbufferGLContext ctx =
@@ -131,15 +152,20 @@ public class X11OnscreenGLContext extends X11GLContext {
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
try {
- super.free();
+ super.releaseImpl();
} finally {
unlockSurface();
}
}
- public synchronized void swapBuffers() throws GLException {
+ protected void destroyImpl() throws GLException {
+ realized = false;
+ super.destroyImpl();
+ }
+
+ public void swapBuffers() throws GLException {
// FIXME: this cast to int would be wrong on 64-bit platforms
// where the argument type to glXMakeCurrent would change (should
// probably make GLXDrawable, and maybe XID, Opaque as long)
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
index 7733472fb..30a60ba61 100644
--- a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
@@ -234,10 +234,10 @@ public class X11PbufferGLContext extends X11GLContext {
}
}
- protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ protected int makeCurrentImpl() throws GLException {
if (buffer == 0) {
// pbuffer not instantiated yet
- return false;
+ return CONTEXT_NOT_CURRENT;
}
lockAWT();
@@ -257,15 +257,15 @@ public class X11PbufferGLContext extends X11GLContext {
if (created) {
resetGLFunctionAvailability();
- initAction.run();
+ return CONTEXT_CURRENT_NEW;
}
- return true;
+ return CONTEXT_CURRENT;
} finally {
unlockAWT();
}
}
- protected synchronized void free() throws GLException {
+ protected void releaseImpl() throws GLException {
lockAWT();
try {
if (!GLX.glXMakeContextCurrent(display, 0, 0, 0)) {