aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games/jogl/impl/windows
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2005-02-26 01:41:28 +0000
committerKenneth Russel <[email protected]>2005-02-26 01:41:28 +0000
commitb41b720c4366d4e2cdc1ba146123b87da966d724 (patch)
tree6c6c8196e9ac0ef57f068f394c1720ec034639c2 /src/net/java/games/jogl/impl/windows
parent2bb02ad536c5404f008ff71c6d4ca013abaff683 (diff)
Merged with current JOGL trunk (tag JOGL_1_1_PRE_B10)
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/branches/JSR-231@245 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/net/java/games/jogl/impl/windows')
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java114
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java51
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java3
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java21
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java94
5 files changed, 218 insertions, 65 deletions
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index eed383794..37a3f5359 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -61,6 +61,7 @@ public abstract class WindowsGLContext extends GLContext {
private GLProcAddressTable glProcAddressTable;
// Handle to GLU32.dll
private long hglu32;
+ private boolean haveWGLARBPbuffer = true;
private static final int MAX_PFORMATS = 256;
private static final int MAX_ATTRIBS = 256;
@@ -141,10 +142,17 @@ public abstract class WindowsGLContext extends GLContext {
if (!WGL.wglMakeCurrent(hdc, hglrc)) {
throw new GLException("Error making context current: " + WGL.GetLastError());
+ } else {
+ if (DEBUG) {
+ System.err.println("wglMakeCurrent(hdc " + hdcToString(hdc) +
+ ", hglrc " + hdcToString(hglrc) + ") succeeded");
+ }
}
if (created) {
resetGLFunctionAvailability();
+ haveWGLARBPbuffer = (isExtensionAvailable("WGL_ARB_pbuffer") &&
+ isExtensionAvailable("WGL_ARB_pixel_format"));
// Windows can set up sharing of display lists after creation time
WindowsGLContext other = (WindowsGLContext) GLContextShareSet.getShareContext(this);
if (other != null) {
@@ -154,7 +162,8 @@ public abstract class WindowsGLContext extends GLContext {
}
if (!WGL.wglShareLists(hglrc2, hglrc)) {
throw new GLException("wglShareLists(0x" + Long.toHexString(hglrc2) +
- ", 0x" + Long.toHexString(hglrc) + ") failed");
+ ", 0x" + Long.toHexString(hglrc) + ") failed: error code " +
+ WGL.GetLastError());
}
}
GLContextShareSet.contextCreated(this);
@@ -302,6 +311,8 @@ public abstract class WindowsGLContext extends GLContext {
freeWGLC = true;
}
}
+ // Fallback path for older cards, in particular Intel Extreme motherboard graphics
+ boolean gotAvailableCaps = false;
if (dummyGL != null && haveWGLChoosePixelFormatARB) {
int[] iattributes = new int [2 * MAX_ATTRIBS];
int[] iresults = new int [2 * MAX_ATTRIBS];
@@ -408,46 +419,54 @@ public abstract class WindowsGLContext extends GLContext {
// 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: " + WGL.GetLastError());
- }
- 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;
- if (haveWGLARBMultisample) {
- iattributes[niattribs++] = GL.WGL_SAMPLE_BUFFERS_ARB;
- iattributes[niattribs++] = GL.WGL_SAMPLES_ARB;
- }
+ if (dummyGL.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, iresults)) {
+ 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;
+ if (haveWGLARBMultisample) {
+ 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 = 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);
+ }
+ if( freeWGLC ) {
+ WGL.wglMakeCurrent( 0, 0 );
+ }
+ gotAvailableCaps = true;
+ } else {
+ int lastErr = WGL.GetLastError();
+ // Intel Extreme graphics fails with a zero error code
+ if (lastErr != 0) {
+ throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError());
}
- availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
- }
- if( freeWGLC ) {
- WGL.wglMakeCurrent( 0, 0 );
}
- } else {
+ }
+
+ if (!gotAvailableCaps) {
if (DEBUG) {
System.err.println("Using ChoosePixelFormat because no wglChoosePixelFormatARB: dummyGL = " + dummyGL);
}
@@ -467,6 +486,7 @@ public abstract class WindowsGLContext extends GLContext {
availableCaps[i] = pfd2GLCapabilities(pfd);
}
}
+
// Supply information to chooser
pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat);
if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
@@ -490,11 +510,17 @@ public abstract class WindowsGLContext extends GLContext {
pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
}
if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) {
- throw new GLException("Unable to set pixel format");
+ int lastError = WGL.GetLastError();
+ if (DEBUG) {
+ System.err.println("SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() +
+ ", current DC = " + WGL.wglGetCurrentDC());
+ System.err.println("GetPixelFormat(hdc " + hdcToString(hdc) + ") returns " + WGL.GetPixelFormat(hdc));
+ }
+ throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + hdcToString(hdc) + ": error code " + lastError);
}
hglrc = WGL.wglCreateContext(hdc);
if (DEBUG) {
- System.err.println("!!! Created OpenGL context " + hglrc);
+ System.err.println("!!! Created OpenGL context " + hglrc + " for device context " + hdcToString(hdc) + " using pixel format " + pixelFormat);
}
if (hglrc == 0) {
throw new GLException("Unable to create OpenGL context");
@@ -654,4 +680,12 @@ public abstract class WindowsGLContext extends GLContext {
}
return res;
}
+
+ protected static String hdcToString(long hdc) {
+ return "0x" + Long.toHexString(hdc);
+ }
+
+ protected boolean haveWGLARBPbuffer() {
+ return haveWGLARBPbuffer;
+ }
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
index 726091bf1..1c976c355 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
@@ -43,6 +43,7 @@ import java.awt.Component;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.Rectangle;
+import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
@@ -74,6 +75,56 @@ public class WindowsGLContextFactory extends GLContextFactory {
AccessController.doPrivileged( new PrivilegedAction() {
public Object run() {
Runtime.getRuntime().addShutdownHook( new ShutdownHook() );
+
+ // Test for whether we should enable the single-threaded
+ // workaround for ATI cards. It appears that if we make any
+ // OpenGL context current on more than one thread on ATI cards
+ // on Windows then we see random failures like the inability
+ // to create more OpenGL contexts, or having just the next
+ // OpenGL SetPixelFormat operation fail with a GetNextError()
+ // code of 0 (but subsequent ones on subsequently-created
+ // windows succeed). These kinds of failures are obviously due
+ // to bugs in ATI's OpenGL drivers. Through trial and error it
+ // was found that specifying
+ // -DJOGL_SINGLE_THREADED_WORKAROUND=true on the command line
+ // caused these problems to completely disappear. Therefore at
+ // least on Windows we try to enable the single-threaded
+ // workaround before creating any OpenGL contexts. In the
+ // future, if problems are encountered on other platforms and
+ // -DJOGL_SINGLE_THREADED_WORKAROUND=true works around them,
+ // we may want to implement a workaround like this on other
+ // platforms.
+
+ // The algorithm here is to try to find the system directory
+ // (assuming it is on the same drive as TMPDIR, exposed
+ // through the system property java.io.tmpdir) and see whether
+ // a known file in the ATI drivers is present; if it is, we
+ // enable the single-threaded workaround.
+
+ // If any path down this code fails, we simply bail out -- we
+ // don't go to great lengths to figure out if the ATI drivers
+ // are present. We could add more checks here in the future if
+ // these appear to be insufficient.
+
+ String tmpDirProp = System.getProperty("java.io.tmpdir");
+ if (tmpDirProp != null) {
+ File file = new File(tmpDirProp);
+ if (file.isAbsolute()) {
+ File parent = null;
+ do {
+ parent = file.getParentFile();
+ if (parent != null) {
+ file = parent;
+ }
+ } while (parent != null);
+ // Now the file contains just the drive letter
+ file = new File(new File(new File(file, "windows"), "system32"), "atioglxx.dll");
+ if (file.exists()) {
+ SingleThreadedWorkaround.shouldDoWorkaround();
+ }
+ }
+ }
+
return( null );
}
});
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
index 9e871caba..5743253a0 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
@@ -172,7 +172,8 @@ public class WindowsOffscreenGLContext extends WindowsGLContext {
}
hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, 0, 0, 0);
if (hbitmap == 0) {
- throw new GLException("Error creating offscreen bitmap");
+ throw new GLException("Error creating offscreen bitmap of width " + width +
+ ", height " + height);
}
if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) {
throw new GLException("Error selecting bitmap into new device context");
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
index 3bfdee5d1..de13be0a1 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -61,6 +61,25 @@ 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
+ // choosePixelFormatAndCreateContext calls
+ // Component.getGraphicsConfiguration(), which grabs the tree
+ // lock. To avoid deadlock we have to lock the tree lock before
+ // grabbing the GLContext's lock if we're going to create an
+ // OpenGL context during this call. This code might not be
+ // completely correct, and we might need to uniformly grab the AWT
+ // tree lock, which might become a performance issue...
+ if (hglrc == 0) {
+ synchronized(component.getTreeLock()) {
+ super.invokeGL(runnable, isReshape, initAction);
+ }
+ } else {
+ super.invokeGL(runnable, isReshape, initAction);
+ }
+ }
+
protected GL createGL()
{
return new WindowsGLImpl(this);
@@ -83,7 +102,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
}
public boolean canCreatePbufferContext() {
- return true;
+ return haveWGLARBPbuffer();
}
public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
index d3795905f..f0ce74d9d 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -43,7 +43,7 @@ import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
public class WindowsPbufferGLContext extends WindowsGLContext {
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = Debug.debug("WindowsPbufferGLContext");
private int initWidth;
private int initHeight;
@@ -75,6 +75,13 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
throw new GLException("Initial width and height of pbuffer must be positive (were (" +
initWidth + ", " + initHeight + "))");
}
+
+ if (DEBUG) {
+ System.out.println("Pbuffer caps on init: " + capabilities +
+ (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+ (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+ (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+ }
}
public boolean canCreatePbufferContext() {
@@ -128,6 +135,13 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
int nfattribs = 0;
int niattribs = 0;
+ if (DEBUG) {
+ System.out.println("Pbuffer caps: " + capabilities +
+ (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+ (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+ (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+ }
+
rtt = capabilities.getOffscreenRenderToTexture();
rect = capabilities.getOffscreenRenderToTextureRectangle();
boolean useFloat = capabilities.getOffscreenFloatingPointBuffers();
@@ -228,9 +242,10 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
iattributes[5] = GL.WGL_FLOAT_COMPONENTS_NV;
iattributes[6] = GL.WGL_SAMPLE_BUFFERS_EXT;
iattributes[7] = GL.WGL_SAMPLES_EXT;
- int[] ivalues = new int[8];
+ iattributes[8] = GL.WGL_DRAW_TO_PBUFFER_ARB;
+ int[] ivalues = new int[9];
for (int i = 0; i < nformats; i++) {
- if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 8, iattributes, ivalues)) {
+ if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, ivalues)) {
throw new GLException("Error while querying pixel format " + pformats[i] +
"'s (index " + i + "'s) capabilities for debugging");
}
@@ -245,38 +260,49 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
if (ivalues[5] != 0) {
System.err.print(" [float]");
}
+ if (ivalues[8] != 0) {
+ System.err.print(" [pbuffer]");
+ }
System.err.println();
}
}
- int format = pformats[0];
+ long tmpBuffer = 0;
+ int whichFormat = 0;
+ // Loop is a workaround for bugs in NVidia's recent drivers
+ do {
+ int format = pformats[whichFormat];
- // Create the p-buffer.
- niattribs = 0;
+ // Create the p-buffer.
+ niattribs = 0;
- if (rtt) {
- iattributes[niattribs++] = GL.WGL_TEXTURE_FORMAT_ARB;
- if (useFloat) {
- iattributes[niattribs++] = GL.WGL_TEXTURE_FLOAT_RGB_NV;
- } else {
- iattributes[niattribs++] = GL.WGL_TEXTURE_RGBA_ARB;
- }
+ if (rtt) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FORMAT_ARB;
+ if (useFloat) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FLOAT_RGB_NV;
+ } else {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_RGBA_ARB;
+ }
- iattributes[niattribs++] = GL.WGL_TEXTURE_TARGET_ARB;
- iattributes[niattribs++] = rect ? GL.WGL_TEXTURE_RECTANGLE_NV : GL.WGL_TEXTURE_2D_ARB;
+ iattributes[niattribs++] = GL.WGL_TEXTURE_TARGET_ARB;
+ iattributes[niattribs++] = rect ? GL.WGL_TEXTURE_RECTANGLE_NV : GL.WGL_TEXTURE_2D_ARB;
- iattributes[niattribs++] = GL.WGL_MIPMAP_TEXTURE_ARB;
- iattributes[niattribs++] = GL.GL_FALSE;
+ iattributes[niattribs++] = GL.WGL_MIPMAP_TEXTURE_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
- iattributes[niattribs++] = GL.WGL_PBUFFER_LARGEST_ARB;
- iattributes[niattribs++] = GL.GL_FALSE;
- }
+ iattributes[niattribs++] = GL.WGL_PBUFFER_LARGEST_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = 0;
- iattributes[niattribs++] = 0;
+ tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes);
+ ++whichFormat;
+ } while ((tmpBuffer == 0) && (whichFormat < nformats));
- long tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes);
if (tmpBuffer == 0) {
- throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: " + wglGetLastError());
+ throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: tried " + nformats +
+ " pixel formats, last error was: " + wglGetLastError());
}
// Get the device context.
@@ -308,10 +334,16 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
if (buffer == 0) {
// pbuffer not instantiated yet
+ if (DEBUG) {
+ System.err.println("pbuffer not instantiated yet");
+ }
return false;
}
boolean res = super.makeCurrent(initAction);
+ if (DEBUG) {
+ System.err.println("super.makeCurrent() = " + res + ", created = " + created);
+ }
if (created) {
// Initialize render-to-texture support if requested
rtt = capabilities.getOffscreenRenderToTexture();
@@ -396,6 +428,22 @@ public class WindowsPbufferGLContext extends WindowsGLContext {
}
}
+ protected void destroyImpl() throws GLException {
+ if (hglrc != 0) {
+ super.destroyImpl();
+ // Must release DC and pbuffer
+ GL gl = getGL();
+ if (gl.wglReleasePbufferDCARB(buffer, hdc) == 0) {
+ throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError());
+ }
+ hdc = 0;
+ if (!gl.wglDestroyPbufferARB(buffer)) {
+ throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError());
+ }
+ buffer = 0;
+ }
+ }
+
public void swapBuffers() throws GLException {
// FIXME: do we need to do anything if the pbuffer is double-buffered?
// For now, just grab the pixels for the render-to-texture support.