aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games/jogl
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2004-04-13 23:55:04 +0000
committerKenneth Russel <[email protected]>2004-04-13 23:55:04 +0000
commitef6a1983a48dd2c3f52987777862c3583ca24c57 (patch)
treeb49fed675a1b3ee74d39747cce928b5e83bc0229 /src/net/java/games/jogl
parentdc4d980ec184d2372b5bde0384ff17cda845c0b5 (diff)
Initial support for multisample / full-scene antialiasing (FSAA);
currently on Windows, X11 and other ports to follow git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@108 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/net/java/games/jogl')
-rw-r--r--src/net/java/games/jogl/GLCapabilities.java30
-rw-r--r--src/net/java/games/jogl/impl/FunctionAvailabilityCache.java17
-rw-r--r--src/net/java/games/jogl/impl/GLContext.java8
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java317
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java59
5 files changed, 381 insertions, 50 deletions
diff --git a/src/net/java/games/jogl/GLCapabilities.java b/src/net/java/games/jogl/GLCapabilities.java
index 389617912..5095c802a 100644
--- a/src/net/java/games/jogl/GLCapabilities.java
+++ b/src/net/java/games/jogl/GLCapabilities.java
@@ -61,6 +61,10 @@ public class GLCapabilities implements Cloneable {
// Shift bits from PIXELFORMATDESCRIPTOR not present because they
// are unlikely to be supported on Windows anyway
+ // Support for full-scene antialiasing (FSAA)
+ private boolean sampleBuffers = false;
+ private int numSamples = 2;
+
// Bits for pbuffer creation
private boolean offscreenFloatingPointBuffers;
private boolean offscreenRenderToTexture;
@@ -245,6 +249,32 @@ public class GLCapabilities implements Cloneable {
this.accumAlphaBits = accumAlphaBits;
}
+ /** Indicates whether sample buffers for full-scene antialiasing
+ (FSAA) should be allocated for this drawable. Defaults to
+ false. */
+ public void setSampleBuffers(boolean onOrOff) {
+ sampleBuffers = onOrOff;
+ }
+
+ /** Returns whether sample buffers for full-scene antialiasing
+ (FSAA) should be allocated for this drawable. Defaults to
+ false. */
+ public boolean getSampleBuffers() {
+ return sampleBuffers;
+ }
+
+ /** If sample buffers are enabled, indicates the number of buffers
+ to be allocated. Defaults to 2. */
+ public void setNumSamples(int numSamples) {
+ this.numSamples = numSamples;
+ }
+
+ /** Returns the number of sample buffers to be allocated if sample
+ buffers are enabled. Defaults to 2. */
+ public int getNumSamples() {
+ return numSamples;
+ }
+
/** For offscreen surfaces only (pbuffers), indicates whether
floating-point buffers should be used if available. Defaults to
false. */
diff --git a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
index 99fb36434..bceb66f9b 100644
--- a/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
+++ b/src/net/java/games/jogl/impl/FunctionAvailabilityCache.java
@@ -52,6 +52,7 @@ import java.lang.reflect.*;
* and display.
*/
public final class FunctionAvailabilityCache {
+ private static final boolean DEBUG = false;
FunctionAvailabilityCache(GLContext context)
{
@@ -70,7 +71,9 @@ public final class FunctionAvailabilityCache {
public boolean isFunctionAvailable(String glFunctionName)
{
- //System.err.println("!!! CHECKING FOR AVAILABILITY OF: "+glFunctionName);
+ if (DEBUG) {
+ System.err.println("!!! CHECKING FOR AVAILABILITY OF: "+ glFunctionName);
+ }
Boolean available = (Boolean)availabilityCache.get(glFunctionName);
@@ -89,6 +92,10 @@ public final class FunctionAvailabilityCache {
availabilityCache.put(glFunctionName, available);
}
+ if (DEBUG) {
+ System.err.println("!!! AVAILABILITY OF "+ glFunctionName + ": " + available.booleanValue());
+ }
+
return available.booleanValue();
}
@@ -102,7 +109,9 @@ public final class FunctionAvailabilityCache {
// of extensions that are in the GL_EXTENSIONS string
if (availableExtensionCache.isEmpty()) {
GL gl = context.getGL();
- //System.err.println("!!! Pre-caching extension availability");
+ if (DEBUG) {
+ System.err.println("!!! Pre-caching extension availability");
+ }
String allAvailableExtensions =
gl.glGetString(GL.GL_EXTENSIONS) + " " + context.getPlatformExtensionsString();
StringTokenizer tok = new StringTokenizer(allAvailableExtensions);
@@ -110,7 +119,9 @@ public final class FunctionAvailabilityCache {
String availableExt = tok.nextToken().trim();
availableExt = availableExt.intern();
availableExtensionCache.add(availableExt);
- //System.err.println("!!! Available: " + availableExt);
+ if (DEBUG) {
+ System.err.println("!!! Available: " + availableExt);
+ }
}
// put a dummy var in here so that the cache is no longer empty even if
diff --git a/src/net/java/games/jogl/impl/GLContext.java b/src/net/java/games/jogl/impl/GLContext.java
index 98e56a314..dbb1194d9 100644
--- a/src/net/java/games/jogl/impl/GLContext.java
+++ b/src/net/java/games/jogl/impl/GLContext.java
@@ -195,7 +195,7 @@ public abstract class GLContext {
if (mustDoMakeCurrent) {
if (curContext != null) {
if (DEBUG) {
- System.err.println("Freeing context " + curContext + " due to recursive makeCurrent");
+ // System.err.println("Freeing context " + curContext + " due to recursive makeCurrent");
}
curContext.free();
}
@@ -211,7 +211,7 @@ public abstract class GLContext {
return;
}
if (DEBUG) {
- System.err.println("Making context " + this + " current");
+ // System.err.println("Making context " + this + " current");
}
}
ctxStack.push(this, initAction);
@@ -265,14 +265,14 @@ public abstract class GLContext {
}
if (DEBUG) {
- System.err.println("Freeing context " + this);
+ // System.err.println("Freeing context " + this);
}
free();
if (curContext != null && !mustFreeBecauseOfNoRenderingThread) {
if (DEBUG) {
- System.err.println("Making context " + curContext + " current again");
+ // System.err.println("Making context " + curContext + " current again");
}
curContext.makeCurrent(curInitAction);
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index f40d7d3d5..5f032f18e 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -40,6 +40,7 @@
package net.java.games.jogl.impl.windows;
import java.awt.Component;
+import java.awt.GraphicsDevice;
import java.util.*;
import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
@@ -59,6 +60,9 @@ public abstract class WindowsGLContext extends GLContext {
// Handle to GLU32.dll
private long hglu32;
+ private static final int MAX_PFORMATS = 256;
+ private static final int MAX_ATTRIBS = 256;
+
static {
functionNameMap = new HashMap();
functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV");
@@ -250,60 +254,198 @@ public abstract class WindowsGLContext extends GLContext {
protected void choosePixelFormatAndCreateContext(boolean onscreen) {
PIXELFORMATDESCRIPTOR pfd = null;
int pixelFormat = 0;
- if (chooser == null) {
- // Note: this code path isn't taken any more now that the
- // DefaultGLCapabilitiesChooser is present. However, it is being
- // left in place for debugging purposes.
- pfd = glCapabilities2PFD(capabilities, onscreen);
- pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
- if (pixelFormat == 0) {
- throw new GLException("Unable to choose appropriate pixel format");
- }
- if (DEBUG) {
- System.err.println("Chosen pixel format from ChoosePixelFormat:");
- PIXELFORMATDESCRIPTOR tmpPFD = new PIXELFORMATDESCRIPTOR();
- WGL.DescribePixelFormat(hdc, pixelFormat, tmpPFD.size(), tmpPFD);
- System.err.println(pfd2GLCapabilities(tmpPFD));
+ if (onscreen) {
+ GLCapabilities[] availableCaps = null;
+ int numFormats = 0;
+ pfd = new PIXELFORMATDESCRIPTOR();
+ GraphicsDevice device = component.getGraphicsConfiguration().getDevice();
+ // Produce a recommended pixel format selection for the GLCapabilitiesChooser.
+ // Try to use wglChoosePixelFormatARB if we have it available
+ GL dummyGL = WindowsGLContextFactory.getDummyGLContext(device);
+ int recommendedPixelFormat = -1;
+ pfd = new PIXELFORMATDESCRIPTOR();
+ boolean haveWGLChoosePixelFormatARB = false;
+ if (dummyGL != null) {
+ // It seems that at this point in initialization,
+ // glGetString(GL.GL_EXTENSIONS) is returning null, so we
+ // need to use wglGetExtensionsStringARB
+ String availableWGLExtensions = dummyGL.wglGetExtensionsStringARB(hdc);
+ if (availableWGLExtensions.indexOf("WGL_ARB_pixel_format") >= 0) {
+ haveWGLChoosePixelFormatARB = true;
+ }
}
- } else {
- if (onscreen) {
- int numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
+ if (dummyGL != null && haveWGLChoosePixelFormatARB) {
+ int[] iattributes = new int [2 * MAX_ATTRIBS];
+ int[] iresults = new int [2 * MAX_ATTRIBS];
+ float[] fattributes = new float[2 * MAX_ATTRIBS];
+ int niattribs = 0;
+ int nfattribs = 0;
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+ iattributes[niattribs++] = GL.WGL_STEREO_ARB;
+ if (capabilities.getStereo()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getRedBits();
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getStencilBits();
+ if (capabilities.getAccumRedBits() > 0 ||
+ capabilities.getAccumGreenBits() > 0 ||
+ capabilities.getAccumBlueBits() > 0 ||
+ capabilities.getAccumAlphaBits() > 0) {
+ iattributes[niattribs++] = GL.WGL_ACCUM_BITS_ARB;
+ iattributes[niattribs++] = (capabilities.getAccumRedBits() +
+ capabilities.getAccumGreenBits() +
+ capabilities.getAccumBlueBits() +
+ capabilities.getAccumAlphaBits());
+ iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumRedBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumGreenBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumBlueBits();
+ iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAccumAlphaBits();
+ }
+ if (capabilities.getSampleBuffers()) {
+ iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
+ iattributes[niattribs++] = capabilities.getNumSamples();
+ }
+
+ int[] pformats = new int[MAX_PFORMATS];
+ int[] numFormatsTmp = new int[1];
+ if (dummyGL.wglChoosePixelFormatARB(hdc,
+ iattributes,
+ fattributes,
+ MAX_PFORMATS,
+ pformats,
+ numFormatsTmp)) {
+ numFormats = numFormatsTmp[0];
+ if (numFormats > 0) {
+ recommendedPixelFormat = pformats[0];
+ if (DEBUG) {
+ System.err.println("Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat);
+ }
+ }
+ }
+ if (DEBUG) {
+ if (recommendedPixelFormat < 0) {
+ System.err.print("wglChoosePixelFormatARB didn't recommend a pixel format");
+ if (capabilities.getSampleBuffers()) {
+ System.err.print(" for multisampled GLCapabilities");
+ }
+ System.err.println();
+ }
+ }
+
+ // Produce a list of GLCapabilities to give to the
+ // GLCapabilitiesChooser.
+ // Use wglGetPixelFormatAttribivARB instead of
+ // DescribePixelFormat to get higher-precision information
+ // about the pixel format (should make the GLCapabilities
+ // more precise as well...i.e., remove the
+ // "HardwareAccelerated" bit, which is basically
+ // meaningless, and put in whether it can render to a
+ // window, to a pbuffer, or to a pixmap)
+ niattribs = 0;
+ iattributes[0] = GL.WGL_NUMBER_PIXEL_FORMATS_ARB;
+ if (!dummyGL.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, iresults)) {
+ throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB");
+ }
+ numFormats = iresults[0];
+ // Should we be filtering out the pixel formats which aren't
+ // applicable, as we are doing here?
+ // We don't have enough information in the GLCapabilities to
+ // represent those that aren't...
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_WINDOW_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCELERATION_ARB;
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ iattributes[niattribs++] = GL.WGL_STEREO_ARB;
+ iattributes[niattribs++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_RED_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_GREEN_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_BLUE_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_ACCUM_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
+ iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
+
+ availableCaps = new GLCapabilities[numFormats];
+ for (int i = 0; i < numFormats; i++) {
+ if (!dummyGL.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, iresults)) {
+ throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context");
+ }
+ availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
+ }
+ } else {
+ if (DEBUG) {
+ System.err.println("Using ChoosePixelFormat because no wglChoosePixelFormatARB: dummyGL = " + dummyGL);
+ }
+ pfd = glCapabilities2PFD(capabilities, onscreen);
+ recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
+
+ numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
if (numFormats == 0) {
throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser");
}
- GLCapabilities[] availableCaps = new GLCapabilities[numFormats];
- pfd = new PIXELFORMATDESCRIPTOR();
+ availableCaps = new GLCapabilities[numFormats];
for (int i = 0; i < numFormats; i++) {
if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) {
throw new GLException("Error describing pixel format " + (1 + i) + " of device context");
}
availableCaps[i] = pfd2GLCapabilities(pfd);
}
- // Supply information to chooser
- // FIXME: should provide a hint to the pixel format selection
- // algorithm, and should be using wglChoosePixelFormatARB in
- // order to do so
- pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, -1);
- if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
- throw new GLException("Invalid result " + pixelFormat +
- " from GLCapabilitiesChooser (should be between 0 and " +
- (numFormats - 1) + ")");
- }
- if (DEBUG) {
- System.err.println("Chosen pixel format (" + pixelFormat + "):");
- System.err.println(availableCaps[pixelFormat]);
- }
- pixelFormat += 1; // one-base the index
- if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
- throw new GLException("Error re-describing the chosen pixel format");
- }
- } else {
- // For now, use ChoosePixelFormat for offscreen surfaces until
- // we figure out how to properly choose an offscreen-
- // compatible pixel format
- pfd = glCapabilities2PFD(capabilities, onscreen);
- pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
}
+ // Supply information to chooser
+ pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat);
+ if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
+ throw new GLException("Invalid result " + pixelFormat +
+ " from GLCapabilitiesChooser (should be between 0 and " +
+ (numFormats - 1) + ")");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen pixel format (" + pixelFormat + "):");
+ System.err.println(availableCaps[pixelFormat]);
+ }
+ pixelFormat += 1; // one-base the index
+ if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
+ throw new GLException("Error re-describing the chosen pixel format");
+ }
+ } else {
+ // For now, use ChoosePixelFormat for offscreen surfaces until
+ // we figure out how to properly choose an offscreen-
+ // compatible pixel format
+ pfd = glCapabilities2PFD(capabilities, onscreen);
+ pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
}
if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) {
throw new GLException("Unable to set pixel format");
@@ -373,4 +515,93 @@ public abstract class WindowsGLContext extends GLContext {
((pfd.dwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0));
return res;
}
+
+ static GLCapabilities iattributes2GLCapabilities(int[] iattribs,
+ int[] iresults,
+ int niattribs,
+ boolean requireRenderToWindow) {
+ GLCapabilities res = new GLCapabilities();
+ for (int i = 0; i < niattribs; i++) {
+ switch (iattribs[i]) {
+ case GL.WGL_DRAW_TO_WINDOW_ARB:
+ if (iresults[i] != GL.GL_TRUE)
+ return null;
+ break;
+
+ case GL.WGL_ACCELERATION_ARB:
+ res.setHardwareAccelerated(iresults[i] == GL.WGL_FULL_ACCELERATION_ARB);
+ break;
+
+ case GL.WGL_SUPPORT_OPENGL_ARB:
+ if (iresults[i] != GL.GL_TRUE)
+ return null;
+ break;
+
+ case GL.WGL_DEPTH_BITS_ARB:
+ res.setDepthBits(iresults[i]);
+ break;
+
+ case GL.WGL_STENCIL_BITS_ARB:
+ res.setStencilBits(iresults[i]);
+ break;
+
+ case GL.WGL_DOUBLE_BUFFER_ARB:
+ res.setDoubleBuffered(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_STEREO_ARB:
+ res.setStereo(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_PIXEL_TYPE_ARB:
+ if (iresults[i] != GL.WGL_TYPE_RGBA_ARB)
+ return null;
+ break;
+
+ case GL.WGL_RED_BITS_ARB:
+ res.setRedBits(iresults[i]);
+ break;
+
+ case GL.WGL_GREEN_BITS_ARB:
+ res.setGreenBits(iresults[i]);
+ break;
+
+ case GL.WGL_BLUE_BITS_ARB:
+ res.setBlueBits(iresults[i]);
+ break;
+
+ case GL.WGL_ALPHA_BITS_ARB:
+ res.setAlphaBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_RED_BITS_ARB:
+ res.setAccumRedBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_GREEN_BITS_ARB:
+ res.setAccumGreenBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_BLUE_BITS_ARB:
+ res.setAccumBlueBits(iresults[i]);
+ break;
+
+ case GL.WGL_ACCUM_ALPHA_BITS_ARB:
+ res.setAccumAlphaBits(iresults[i]);
+ break;
+
+ case GL.WGL_SAMPLE_BUFFERS_ARB:
+ res.setSampleBuffers(iresults[i] == GL.GL_TRUE);
+ break;
+
+ case GL.WGL_SAMPLES_ARB:
+ res.setNumSamples(iresults[i]);
+ break;
+
+ default:
+ throw new GLException("Unknown pixel format attribute " + iattribs[i]);
+ }
+ }
+ return res;
+ }
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
index 0c8d54431..57d4333be 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
@@ -40,12 +40,31 @@
package net.java.games.jogl.impl.windows;
import java.awt.Component;
+import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class WindowsGLContextFactory extends GLContextFactory {
+ // On Windows we want to be able to use some extension routines like
+ // wglChoosePixelFormatARB during the creation of the user's first
+ // GLContext. However, this and other routines' function pointers
+ // aren't loaded by the driver until the first OpenGL context is
+ // created. The standard way of working around this chicken-and-egg
+ // problem is to create a dummy window, show it, send it a paint
+ // message, create an OpenGL context, fetch the needed function
+ // pointers, and then destroy the dummy window and context. In JOGL
+ // since we closely associate the contexts with components we leave
+ // the dummy window around as it should not have a large footprint
+ // impact.
+ private static Map/*<GraphicsDevice, GL>*/ dummyContextMap = new HashMap();
+ private static Set/*<GraphicsDevice >*/ pendingContextSet = new HashSet();
+
public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
GraphicsDevice device) {
@@ -62,4 +81,44 @@ public class WindowsGLContextFactory extends GLContextFactory {
return new WindowsOffscreenGLContext(capabilities, chooser, shareWith);
}
}
+
+ public static GL getDummyGLContext(final GraphicsDevice device) {
+ GL gl = (GL) dummyContextMap.get(device);
+ if (gl != null) {
+ return gl;
+ }
+
+ if (!pendingContextSet.contains(device)) {
+ pendingContextSet.add(device);
+ GraphicsConfiguration config = device.getDefaultConfiguration();
+ Frame frame = new Frame(config);
+ frame.setUndecorated(true);
+ GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities(),
+ null,
+ null,
+ device);
+ canvas.addGLEventListener(new GLEventListener() {
+ public void init(GLDrawable drawable) {
+ pendingContextSet.remove(device);
+ dummyContextMap.put(device, drawable.getGL());
+ }
+
+ public void display(GLDrawable drawable) {
+ }
+
+ public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
+ }
+
+ public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
+ }
+ });
+ canvas.setSize(0, 0);
+ frame.add(canvas);
+ frame.pack();
+ frame.show();
+ canvas.display();
+ }
+
+ return (GL) dummyContextMap.get(device);
+ }
}