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/GLContext.java48
-rw-r--r--src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java70
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java83
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java4
-rw-r--r--src/net/java/games/jogl/impl/x11/X11GLContext.java95
-rw-r--r--src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java24
-rw-r--r--src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java338
7 files changed, 479 insertions, 183 deletions
diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java
index 98b1c6065..eb7d21988 100644
--- a/src/net/java/games/jogl/impl/GLContext.java
+++ b/src/net/java/games/jogl/impl/GLContext.java
@@ -42,6 +42,7 @@ package net.java.games.jogl.impl;
import java.awt.Component;
import java.awt.EventQueue;
import net.java.games.jogl.*;
+import net.java.games.gluegen.runtime.*;
public abstract class GLContext {
protected static final boolean DEBUG = false;
@@ -75,8 +76,10 @@ public abstract class GLContext {
// All GLU interfaces eventually route calls down to gluRoot. It can be
// static because GLU it doesn't actually need to own context, it just makes
// GL calls and assumes some context is active.
- protected static final GLU gluRoot = new GLUImpl();
- protected static GLU glu = gluRoot; // this is the context's GLU interface
+ protected static final GLUProcAddressTable gluProcAddressTable = new GLUProcAddressTable();
+ protected static final GLU gluRoot = new GLUImpl(gluProcAddressTable);
+ protected static boolean haveResetGLUProcAddressTable;
+ protected GLU glu = gluRoot; // this is the context's GLU interface
protected Thread renderingThread;
protected Runnable deferredReshapeAction;
@@ -282,6 +285,13 @@ public abstract class GLContext {
*/
protected void resetGLFunctionAvailability() {
functionAvailability.flush();
+ if (!haveResetGLUProcAddressTable) {
+ if (DEBUG) {
+ System.err.println("!!! Initializing GLU extension address table");
+ }
+ resetProcAddressTable(gluProcAddressTable);
+ haveResetGLUProcAddressTable = true; // Only need to do this once globally
+ }
}
/**
@@ -391,6 +401,40 @@ public abstract class GLContext {
conditions cause a GLException to be thrown. */
protected abstract void swapBuffers() throws GLException;
+ /** 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);
+
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
index 23367c045..d35392ac1 100644
--- a/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
+++ b/src/net/java/games/jogl/impl/macosx/MacOSXGLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.macosx;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -49,6 +49,9 @@ public abstract class MacOSXGLContext extends GLContext
{
private static JAWT jawt;
protected long nsContext; // NSOpenGLContext
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
public MacOSXGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser)
{
@@ -90,74 +93,25 @@ public abstract class MacOSXGLContext extends GLContext
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ return CGL.getProcAddress(glFuncName);
+ }
protected void resetGLFunctionAvailability()
{
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable()
- {
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
-
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- 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(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = CGL.getProcAddress(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
- }
-
+ resetProcAddressTable(getGLProcAddressTable());
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable()
+ public GLProcAddressTable getGLProcAddressTable()
{
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -171,10 +125,6 @@ public abstract class MacOSXGLContext extends GLContext
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT()
{
if (jawt == null)
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index 4575b6210..5a6021acf 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.windows;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -53,6 +53,11 @@ public abstract class WindowsGLContext extends GLContext {
private boolean wglGetExtensionsStringEXTAvailable;
private static final Map/*<String, String>*/ functionNameMap;
private static final Map/*<String, String>*/ extensionNameMap;
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
+ // Handle to GLU32.dll
+ private long hglu32;
static {
functionNameMap = new HashMap();
@@ -132,72 +137,34 @@ public abstract class WindowsGLContext extends GLContext {
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ long res = WGL.wglGetProcAddress(glFuncName);
+ if (res == 0) {
+ // GLU routines aren't known to the OpenGL function lookup
+ if (hglu32 == 0) {
+ hglu32 = WGL.LoadLibraryA("GLU32");
+ if (hglu32 == 0) {
+ throw new GLException("Error loading GLU32.DLL");
+ }
+ }
+ res = WGL.GetProcAddress(hglu32, glFuncName);
+ }
+ return res;
+ }
protected void resetGLFunctionAvailability() {
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable() {
-
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
-
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- 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(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = WGL.wglGetProcAddress(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
- }
-
+ resetProcAddressTable(getGLProcAddressTable());
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() {
+ public GLProcAddressTable getGLProcAddressTable() {
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -234,10 +201,6 @@ public abstract class WindowsGLContext extends GLContext {
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT() {
if (jawt == null) {
JAWT j = new JAWT();
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index 300e9cb85..484c8f8af 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -119,6 +119,10 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
public void createPbuffer(long parentHdc, long parentHglrc) {
GL gl = getGL();
+ // Must initally grab OpenGL function pointers while parent's
+ // context is current because otherwise we don't have the wgl
+ // extensions available to us
+ resetGLFunctionAvailability();
int[] iattributes = new int [2*MAX_ATTRIBS];
float[] fattributes = new float[2*MAX_ATTRIBS];
diff --git a/src/net/java/games/jogl/impl/x11/X11GLContext.java b/src/net/java/games/jogl/impl/x11/X11GLContext.java
index 8e9804578..ec430bfe8 100644
--- a/src/net/java/games/jogl/impl/x11/X11GLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11GLContext.java
@@ -41,7 +41,7 @@ package net.java.games.jogl.impl.x11;
import java.awt.Component;
import java.util.*;
-import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -53,6 +53,11 @@ public abstract class X11GLContext extends GLContext {
private boolean glXQueryExtensionsStringInitialized;
private boolean glXQueryExtensionsStringAvailable;
private static final Map/*<String, String>*/ functionNameMap;
+ private boolean isGLX13;
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private GLProcAddressTable glProcAddressTable;
+ private static boolean haveResetGLXProcAddressTable;
static {
functionNameMap = new HashMap();
@@ -105,6 +110,14 @@ public abstract class X11GLContext extends GLContext {
*/
protected abstract void create();
+ public boolean isExtensionAvailable(String glExtensionName) {
+ if (glExtensionName.equals("GL_ARB_pbuffer") ||
+ glExtensionName.equals("GL_ARB_pixel_format")) {
+ return isGLX13;
+ }
+ return super.isExtensionAvailable(glExtensionName);
+ }
+
protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
boolean created = false;
if (context == 0) {
@@ -140,72 +153,44 @@ public abstract class X11GLContext extends GLContext {
protected abstract void swapBuffers() throws GLException;
+ protected long dynamicLookupFunction(String glFuncName) {
+ long res = GLX.glXGetProcAddressARB(glFuncName);
+ if (res == 0) {
+ // GLU routines aren't known to the OpenGL function lookup
+ res = GLX.dlsym(glFuncName);
+ }
+ return res;
+ }
protected void resetGLFunctionAvailability() {
super.resetGLFunctionAvailability();
- resetGLProcAddressTable();
- }
-
- protected void resetGLProcAddressTable() {
-
if (DEBUG) {
System.err.println("!!! Initializing OpenGL extension address table");
}
+ resetProcAddressTable(getGLProcAddressTable());
- net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
-
- // if GL is no longer an interface, we'll have to re-implement the code
- // below so it only iterates through gl methods (a non-interface might
- // have constructors, custom methods, etc). For now we assume all methods
- // will be gl methods.
- GL gl = getGL();
-
- 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(GLEmitter.PROCADDRESS_VAR_PREFIX))
- {
- // not a proc address variable
- continue;
- }
- int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
- String glFuncName = addressFieldName.substring(startOfMethodName);
- try
- {
- java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
- assert(addressField.getType() == Long.TYPE);
- // get the current value of the proc address variable in the table object
- long oldProcAddress = addressField.getLong(table);
- long newProcAddress = GLX.glXGetProcAddressARB(glFuncName);
- /*
- System.err.println(
- "!!! Address=" + (newProcAddress == 0
- ? "<NULL> "
- : ("0x" +
- Long.toHexString(newProcAddress))) +
- "\tGL func: " + glFuncName);
- */
- // set the current value of the proc address variable in the table object
- addressField.setLong(gl, newProcAddress);
- } catch (Exception e) {
- throw new GLException(
- "Cannot get GL proc address for method \"" +
- glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
- "\" in class " + tableClass.getName(), e);
- }
+ if (!haveResetGLXProcAddressTable) {
+ resetProcAddressTable(GLX.getGLXProcAddressTable());
}
+ // Figure out whether we are running GLX version 1.3 or above and
+ // therefore have pbuffer support
+ if (display == 0) {
+ throw new GLException("Expected non-null DISPLAY for querying GLX version");
+ }
+ int[] major = new int[1];
+ int[] minor = new int[1];
+ if (!GLX.glXQueryVersion(display, major, minor)) {
+ throw new GLException("glXQueryVersion failed");
+ }
+ isGLX13 = ((major[0] > 1) || (minor[0] > 2));
}
- public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() {
+ public GLProcAddressTable getGLProcAddressTable() {
if (glProcAddressTable == null) {
// FIXME: cache ProcAddressTables by capability bits so we can
// share them among contexts with the same capabilities
- glProcAddressTable =
- new net.java.games.jogl.impl.ProcAddressTable();
+ glProcAddressTable = new GLProcAddressTable();
}
return glProcAddressTable;
}
@@ -245,10 +230,6 @@ public abstract class X11GLContext extends GLContext {
// Internals only below this point
//
- // Table that holds the addresses of the native C-language entry points for
- // OpenGL functions.
- private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
-
protected JAWT getJAWT() {
if (jawt == null) {
JAWT j = new JAWT();
diff --git a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
index 496e113a5..385874da7 100644
--- a/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/x11/X11OnscreenGLContext.java
@@ -40,6 +40,8 @@
package net.java.games.jogl.impl.x11;
import java.awt.Component;
+import java.util.*;
+
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -49,6 +51,9 @@ public class X11OnscreenGLContext extends X11GLContext {
private JAWT_DrawingSurfaceInfo dsi;
private JAWT_X11DrawingSurfaceInfo x11dsi;
+ // Variables for pbuffer support
+ List pbuffersToInstantiate = new ArrayList();
+
public X11OnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
super(component, capabilities, chooser);
}
@@ -75,14 +80,16 @@ public class X11OnscreenGLContext extends X11GLContext {
}
public boolean canCreatePbufferContext() {
- // For now say no
- return false;
+ // FIXME: should we gate this on GLX 1.3 being available?
+ return true;
}
public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
int initialWidth,
int initialHeight) {
- throw new GLException("Not yet supported");
+ X11PbufferGLContext ctx = new X11PbufferGLContext(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(ctx);
+ return ctx;
}
public void bindPbufferToTexture() {
@@ -98,7 +105,16 @@ public class X11OnscreenGLContext extends X11GLContext {
if (!lockSurface()) {
return false;
}
- return super.makeCurrent(initAction);
+ boolean ret = super.makeCurrent(initAction);
+ if (ret) {
+ // Instantiate any pending pbuffers
+ while (!pbuffersToInstantiate.isEmpty()) {
+ X11PbufferGLContext ctx =
+ (X11PbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ ctx.createPbuffer(display, context);
+ }
+ }
+ return ret;
} catch (RuntimeException e) {
try {
unlockSurface();
diff --git a/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
new file mode 100644
index 000000000..264d60fc7
--- /dev/null
+++ b/src/net/java/games/jogl/impl/x11/X11PbufferGLContext.java
@@ -0,0 +1,338 @@
+/*
+ * 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.x11;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class X11PbufferGLContext extends X11GLContext {
+ private static final boolean DEBUG = false;
+
+ private int initWidth;
+ private int initHeight;
+
+ private long buffer; // GLXPbuffer
+ private GLXFBConfig fbConfig;
+ private int width;
+ private int height;
+
+ // FIXME: kept around because we create the OpenGL context lazily to
+ // better integrate with the X11GLContext framework
+ private long parentContext;
+
+ private static final int MAX_PFORMATS = 256;
+ private static final int MAX_ATTRIBS = 256;
+
+ // FIXME: figure out how to support render-to-texture and
+ // render-to-texture-rectangle (which appear to be supported, though
+ // it looks like floating-point buffers are not)
+
+ public X11PbufferGLContext(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(null, capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ if (initWidth <= 0 || initHeight <= 0) {
+ throw new GLException("Initial width and height of pbuffer must be positive (were (" +
+ initWidth + ", " + initHeight + "))");
+ }
+ }
+
+ public boolean canCreatePbufferContext() {
+ return false;
+ }
+
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ throw new GLException("Not supported");
+ }
+
+ public void bindPbufferToTexture() {
+ // FIXME: figure out how to implement this
+ throw new GLException("Not yet implemented");
+ }
+
+ public void releasePbufferFromTexture() {
+ // FIXME: figure out how to implement this
+ throw new GLException("Not yet implemented");
+ }
+
+ public void createPbuffer(long display, long parentContext) {
+ if (display == 0) {
+ throw new GLException("Null display");
+ }
+
+ if (parentContext == 0) {
+ throw new GLException("Null parentContext");
+ }
+
+ if (capabilities.getOffscreenFloatingPointBuffers()) {
+ throw new GLException("Floating-point pbuffers not supported yet on X11");
+ }
+
+ if (capabilities.getOffscreenRenderToTexture()) {
+ throw new GLException("Render-to-texture pbuffers not supported yet on X11");
+ }
+
+ if (capabilities.getOffscreenRenderToTextureRectangle()) {
+ throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
+ }
+
+ int[] iattributes = new int [2*MAX_ATTRIBS];
+ float[] fattributes = new float[2*MAX_ATTRIBS];
+ int nfattribs = 0;
+ int niattribs = 0;
+
+ // Since we are trying to create a pbuffer, the GLXFBConfig we
+ // request (and subsequently use) must be "p-buffer capable".
+ iattributes[niattribs++] = GL.GLX_DRAWABLE_TYPE;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_BIT;
+
+ iattributes[niattribs++] = GL.GLX_RENDER_TYPE;
+ iattributes[niattribs++] = GL.GLX_RGBA_BIT;
+
+ iattributes[niattribs++] = GLX.GLX_DOUBLEBUFFER;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = GLX.GLX_DEPTH_SIZE;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+
+ iattributes[niattribs++] = GLX.GLX_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getRedBits();
+
+ iattributes[niattribs++] = GLX.GLX_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+
+ iattributes[niattribs++] = GLX.GLX_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+
+ iattributes[niattribs++] = GLX.GLX_ALPHA_SIZE;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+
+ if (capabilities.getStencilBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_STENCIL_SIZE;
+ iattributes[niattribs++] = capabilities.getStencilBits();
+ }
+
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0) {
+ iattributes[niattribs++] = GLX.GLX_ACCUM_RED_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumRedBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_GREEN_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumGreenBits();
+ iattributes[niattribs++] = GLX.GLX_ACCUM_BLUE_SIZE;
+ iattributes[niattribs++] = capabilities.getAccumBlueBits();
+ }
+
+ iattributes[niattribs++] = 0; // null-terminate
+
+ int screen = 0; // FIXME: provide way to specify this?
+ int[] nelementsTmp = new int[1];
+ GLXFBConfig[] fbConfigs = GLX.glXChooseFBConfig(display, screen, iattributes, nelementsTmp);
+ if (fbConfigs == null || fbConfigs.length == 0 || fbConfigs[0] == null) {
+ throw new GLException("pbuffer creation error: glXChooseFBConfig() failed");
+ }
+ // Note that we currently don't allow selection of anything but
+ // the first GLXFBConfig in the returned list
+ GLXFBConfig fbConfig = fbConfigs[0];
+ int nelements = nelementsTmp[0];
+ if (nelements <= 0) {
+ throw new GLException("pbuffer creation error: couldn't find a suitable frame buffer configuration");
+ }
+
+ if (DEBUG) {
+ System.err.println("Found " + fbConfigs.length + " matching GLXFBConfigs");
+ System.err.println("Parameters of default one:");
+ System.err.println("render type: 0x" + Integer.toHexString(queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE)));
+ System.err.println("rgba: " + ((queryFBConfig(display, fbConfig, GLX.GLX_RENDER_TYPE) & GLX.GLX_RGBA_BIT) != 0));
+ System.err.println("r: " + queryFBConfig(display, fbConfig, GLX.GLX_RED_SIZE));
+ System.err.println("g: " + queryFBConfig(display, fbConfig, GLX.GLX_GREEN_SIZE));
+ System.err.println("b: " + queryFBConfig(display, fbConfig, GLX.GLX_BLUE_SIZE));
+ System.err.println("a: " + queryFBConfig(display, fbConfig, GLX.GLX_ALPHA_SIZE));
+ System.err.println("depth: " + queryFBConfig(display, fbConfig, GLX.GLX_DEPTH_SIZE));
+ System.err.println("double buffered: " + queryFBConfig(display, fbConfig, GLX.GLX_DOUBLEBUFFER));
+ }
+
+ // Create the p-buffer.
+ niattribs = 0;
+
+ iattributes[niattribs++] = GL.GLX_PBUFFER_WIDTH;
+ iattributes[niattribs++] = initWidth;
+ iattributes[niattribs++] = GL.GLX_PBUFFER_HEIGHT;
+ iattributes[niattribs++] = initHeight;
+
+ iattributes[niattribs++] = 0;
+
+ int tmpBuffer = GLX.glXCreatePbuffer(display, fbConfig, iattributes);
+ if (tmpBuffer == 0) {
+ // FIXME: query X error code for detail error message
+ throw new GLException("pbuffer creation error: glXCreatePbuffer() failed");
+ }
+
+ // Set up instance variables
+ this.display = display;
+ this.parentContext = parentContext;
+ buffer = tmpBuffer;
+ this.fbConfig = fbConfig;
+
+ // Determine the actual width and height we were able to create.
+ int[] tmp = new int[1];
+ GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_WIDTH, tmp);
+ width = tmp[0];
+ GLX.glXQueryDrawable(display, (int) buffer, GL.GLX_HEIGHT, tmp);
+ height = tmp[0];
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer " + width + " x " + height);
+ }
+ }
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ if (buffer == 0) {
+ // pbuffer not instantiated yet
+ return false;
+ }
+
+ lockAWT();
+ try {
+ boolean created = false;
+ if (context == 0) {
+ create();
+ if (DEBUG) {
+ System.err.println("!!! Created GL context for " + getClass().getName());
+ }
+ created = true;
+ }
+
+ // 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)
+ if (!GLX.glXMakeContextCurrent(display, (int) buffer, (int) buffer, context)) {
+ throw new GLException("Error making context current");
+ }
+
+ if (created) {
+ resetGLFunctionAvailability();
+ initAction.run();
+ }
+ return true;
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ protected synchronized void free() throws GLException {
+ lockAWT();
+ try {
+ if (!GLX.glXMakeContextCurrent(display, 0, 0, 0)) {
+ throw new GLException("Error freeing OpenGL context");
+ }
+ } finally {
+ unlockAWT();
+ }
+ }
+
+ public void handleModeSwitch(long parentHdc, long parentHglrc) {
+ throw new GLException("Not yet implemented");
+ }
+
+ protected boolean isOffscreen() {
+ // FIXME: currently the only caller of this won't cause proper
+ // resizing of the pbuffer anyway.
+ return false;
+ }
+
+ public int getOffscreenContextBufferedImageType() {
+ throw new GLException("Should not call this");
+ }
+
+ public int getOffscreenContextReadBuffer() {
+ throw new GLException("Should not call this");
+ }
+
+ public boolean offscreenImageNeedsVerticalFlip() {
+ throw new GLException("Should not call this");
+ }
+
+ protected void create() {
+ if (DEBUG) {
+ System.err.println("Creating context for pbuffer " + width + " x " + height);
+ }
+
+ // Create a gl context for the p-buffer.
+ // FIXME: provide option to not share display lists with subordinate pbuffer?
+ context = GLX.glXCreateNewContext(display, fbConfig, GL.GLX_RGBA_TYPE, parentContext, true);
+ if (context == 0) {
+ throw new GLException("pbuffer creation error: glXCreateNewContext() failed");
+ }
+
+ if (DEBUG) {
+ System.err.println("Created context for pbuffer " + width + " x " + height);
+ }
+ }
+
+ protected void swapBuffers() throws GLException {
+ // FIXME: do we need to do anything if the pbuffer is double-buffered?
+ }
+
+ private int queryFBConfig(long display, GLXFBConfig fbConfig, int attrib) {
+ int[] tmp = new int[1];
+ if (GLX.glXGetFBConfigAttrib(display, fbConfig, attrib, tmp) != 0) {
+ throw new GLException("glXGetFBConfigAttrib failed");
+ }
+ return tmp[0];
+ }
+
+ // These synchronization primitives, which prevent the AWT from
+ // making requests from the X server asynchronously to this code,
+ // are required for pbuffers to work properly on X11.
+ private void lockAWT() {
+ getJAWT().Lock();
+ }
+
+ private void unlockAWT() {
+ getJAWT().Unlock();
+ }
+}