From d6f9dbc493df725d3d574403549de142c5e1222a Mon Sep 17 00:00:00 2001
From: Kenneth Russel <kbrussel@alum.mit.edu>
Date: Mon, 24 Oct 2005 19:21:03 +0000
Subject: Merged JSR-231 branch on to the main JOGL trunk. The main trunk now
 contains the evolving JSR-231 Reference Implementation and the JSR-231 branch
 is permanently closed.

git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@401 232f8b59-042b-4e1e-8c03-345bb8c30851
---
 .../impl/windows/WindowsDummyGLDrawable.java       |  97 ++++
 .../impl/windows/WindowsExternalGLContext.java     |  77 ++++
 .../impl/windows/WindowsExternalGLDrawable.java    |  69 +++
 .../sun/opengl/impl/windows/WindowsGLContext.java  | 286 ++++++++++++
 .../sun/opengl/impl/windows/WindowsGLDrawable.java | 502 +++++++++++++++++++++
 .../impl/windows/WindowsGLDrawableFactory.java     | 223 +++++++++
 .../impl/windows/WindowsOffscreenGLContext.java    |  64 +++
 .../impl/windows/WindowsOffscreenGLDrawable.java   | 133 ++++++
 .../impl/windows/WindowsOnscreenGLContext.java     |  93 ++++
 .../impl/windows/WindowsOnscreenGLDrawable.java    | 198 ++++++++
 .../impl/windows/WindowsPbufferGLContext.java      | 163 +++++++
 .../impl/windows/WindowsPbufferGLDrawable.java     | 399 ++++++++++++++++
 12 files changed, 2304 insertions(+)
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsDummyGLDrawable.java
 create mode 100755 src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
 create mode 100755 src/classes/com/sun/opengl/impl/windows/WindowsExternalGLDrawable.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsGLDrawable.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsGLDrawableFactory.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLContext.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLDrawable.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLContext.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLDrawable.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLContext.java
 create mode 100644 src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLDrawable.java

(limited to 'src/classes/com/sun/opengl/impl/windows')

diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsDummyGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsDummyGLDrawable.java
new file mode 100644
index 000000000..d57ddec2a
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsDummyGLDrawable.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsDummyGLDrawable extends WindowsGLDrawable {
+  private long hwnd;
+
+  public WindowsDummyGLDrawable() {
+    super(null, new GLCapabilities(), null);
+    // All entries to CreateDummyWindow must synchronize on one object
+    // to avoid accidentally registering the dummy window class twice
+    synchronized (WindowsDummyGLDrawable.class) {
+      hwnd = WGL.CreateDummyWindow(0, 0, 1, 1);
+    }
+    hdc = WGL.GetDC(hwnd);
+    // Choose a (hopefully hardware-accelerated) OpenGL pixel format for this device context
+    GLCapabilities caps = new GLCapabilities();
+    caps.setDepthBits(16);
+    PIXELFORMATDESCRIPTOR pfd = glCapabilities2PFD(caps, true);
+    int pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
+    if ((pixelFormat == 0) ||
+        (!WGL.SetPixelFormat(hdc, pixelFormat, pfd))) {
+      destroy();
+    }
+  }
+
+  public void setSize(int width, int height) {
+  }
+
+  public int getWidth() {
+    return 1;
+  }
+
+  public int getHeight() {
+    return 1;
+  }
+
+  public GLContext createContext(GLContext shareWith) {
+    if (hdc == 0) {
+      // Construction failed
+      return null;
+    }
+    return new WindowsGLContext(this, shareWith);
+  }
+
+  public void destroy() {
+    if (hdc != 0) {
+      WGL.ReleaseDC(hwnd, hdc);
+      hdc = 0;
+    }
+    if (hwnd != 0) {
+      WGL.ShowWindow(hwnd, WGL.SW_HIDE);
+      WGL.DestroyWindow(hwnd);
+      hwnd = 0;
+    }
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
new file mode 100755
index 000000000..694aa6b0d
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLContext.java
@@ -0,0 +1,77 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.nio.*;
+import java.util.*;
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsExternalGLContext extends WindowsGLContext {
+  private boolean firstMakeCurrent = true;
+  private boolean created = true;
+
+  public WindowsExternalGLContext() {
+    super(null, null);
+    hglrc = WGL.wglGetCurrentContext();
+    GLContextShareSet.contextCreated(this);
+    resetGLFunctionAvailability();
+  }
+
+  protected int makeCurrentImpl() throws GLException {
+    if (firstMakeCurrent) {
+      firstMakeCurrent = false;
+      return CONTEXT_CURRENT_NEW;
+    }
+    return CONTEXT_CURRENT;
+  }
+
+  protected void releaseImpl() throws GLException {
+  }
+
+  protected void destroyImpl() throws GLException {
+    created = false;
+    GLContextShareSet.contextDestroyed(this);
+  }
+
+  public boolean isCreated() {
+    return created;
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLDrawable.java
new file mode 100755
index 000000000..f934c1d23
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsExternalGLDrawable.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsExternalGLDrawable extends WindowsGLDrawable {
+  public WindowsExternalGLDrawable() {
+    super(null, new GLCapabilities(), null);
+    hdc = WGL.wglGetCurrentDC();
+  }
+
+  public GLContext createContext(GLContext shareWith) {
+    return new WindowsGLContext(this, shareWith);
+  }
+  
+  public void setSize(int newWidth, int newHeight) {
+    throw new GLException("Should not call this");
+  }
+
+  public int getWidth() {
+    throw new GLException("Should not call this");
+  }  
+
+  public int getHeight() {
+    throw new GLException("Should not call this");
+  }  
+
+  public void destroy() {
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
new file mode 100644
index 000000000..d4b10dbfb
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsGLContext.java
@@ -0,0 +1,286 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.nio.*;
+import java.util.*;
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsGLContext extends GLContextImpl {
+  protected WindowsGLDrawable drawable;
+  protected long hglrc;
+  private boolean wglGetExtensionsStringEXTInitialized;
+  private boolean wglGetExtensionsStringEXTAvailable;
+  private static final Map/*<String, String>*/ functionNameMap;
+  private static final Map/*<String, String>*/ extensionNameMap;
+  private WGLExt wglExt;
+  // Table that holds the addresses of the native C-language entry points for
+  // WGL extension functions.
+  private WGLExtProcAddressTable wglExtProcAddressTable;
+
+  static {
+    functionNameMap = new HashMap();
+    functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV");
+    functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV");
+
+    extensionNameMap = new HashMap();
+    extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer");
+    extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format");
+  }
+
+  public WindowsGLContext(WindowsGLDrawable drawable,
+                          GLContext shareWith) {
+    super(shareWith);
+    this.drawable = drawable;
+  }
+  
+  public Object getPlatformGLExtensions() {
+    return getWGLExt();
+  }
+
+  public WGLExt getWGLExt() {
+    if (wglExt == null) {
+      wglExt = new WGLExtImpl(this);
+    }
+    return wglExt;
+  }
+
+  public GLDrawable getGLDrawable() {
+    return drawable;
+  }
+
+  protected String mapToRealGLFunctionName(String glFunctionName) {
+    String lookup = (String) functionNameMap.get(glFunctionName);
+    if (lookup != null) {
+      return lookup;
+    }
+    return glFunctionName;
+  }
+
+  protected String mapToRealGLExtensionName(String glExtensionName) {
+    String lookup = (String) extensionNameMap.get(glExtensionName);
+    if (lookup != null) {
+      return lookup;
+    }
+    return glExtensionName;
+  }
+
+  /**
+   * Creates and initializes an appropriate OpenGL context. Should only be
+   * called by {@link #makeCurrentImpl()}.
+   */
+  protected void create() {
+    if (drawable.getHDC() == 0) {
+      throw new GLException("Internal error: attempted to create OpenGL context without an associated drawable");
+    }
+    hglrc = WGL.wglCreateContext(drawable.getHDC());
+    if (hglrc == 0) {
+      throw new GLException("Unable to create OpenGL context for device context " + toHexString(drawable.getHDC()));
+    }
+    // Windows can set up sharing of display lists after creation time
+    WindowsGLContext other = (WindowsGLContext) GLContextShareSet.getShareContext(this);
+    long hglrc2 = 0;
+    if (other != null) {
+      hglrc2 = other.getHGLRC();
+      if (hglrc2 == 0) {
+        throw new GLException("GLContextShareSet returned an invalid OpenGL context");
+      }
+      if (!WGL.wglShareLists(hglrc2, hglrc)) {
+        throw new GLException("wglShareLists(" + toHexString(hglrc2) +
+                              ", " + toHexString(hglrc) + ") failed: error code " +
+                              WGL.GetLastError());
+      }
+    }
+    GLContextShareSet.contextCreated(this);      
+    if (DEBUG) {
+      System.err.println(getThreadName() + ": !!! Created OpenGL context " + toHexString(hglrc) + " for " + this + ", device context " + toHexString(drawable.getHDC()) + ", sharing with " + toHexString(hglrc2));
+    }
+  }
+  
+  protected int makeCurrentImpl() throws GLException {
+    boolean created = false;
+    if (hglrc == 0) {
+      create();
+      if (DEBUG) {
+        System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName());
+      }
+      created = true;
+    }
+
+    boolean skipMakeCurrent = false;
+    if (NO_FREE) {
+      if (WGL.wglGetCurrentContext() == hglrc) {
+        if (DEBUG && VERBOSE) {
+          System.err.println(getThreadName() + ": skipping wglMakeCurrent because context already current");
+        }
+        skipMakeCurrent = true;
+      }
+    }
+
+    if (!skipMakeCurrent) {
+      if (!WGL.wglMakeCurrent(drawable.getHDC(), hglrc)) {
+        throw new GLException("Error making context current: " + WGL.GetLastError());
+      } else {
+        if (DEBUG && VERBOSE) {
+          System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getHDC()) +
+                             ", hglrc " + toHexString(hglrc) + ") succeeded");
+        }
+      }
+    }
+
+    if (created) {
+      resetGLFunctionAvailability();
+      return CONTEXT_CURRENT_NEW;
+    }
+    return CONTEXT_CURRENT;
+  }
+
+  protected void releaseImpl() throws GLException {
+    if (!NO_FREE) {
+      if (!WGL.wglMakeCurrent(0, 0)) {
+        throw new GLException("Error freeing OpenGL context: " + WGL.GetLastError());
+      }
+    }
+  }
+
+  protected void destroyImpl() throws GLException {
+    if (hglrc != 0) {
+      if (!WGL.wglDeleteContext(hglrc)) {
+        throw new GLException("Unable to delete OpenGL context");
+      }
+      if (DEBUG) {
+        System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc));
+      }
+      hglrc = 0;
+      GLContextShareSet.contextDestroyed(this);
+    }
+  }
+
+  public boolean isCreated() {
+    return (hglrc != 0);
+  }
+
+  protected void resetGLFunctionAvailability() {
+    super.resetGLFunctionAvailability();
+    if (DEBUG) {
+      System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this);
+    }
+    resetProcAddressTable(getWGLExtProcAddressTable());
+  }
+  
+  public WGLExtProcAddressTable getWGLExtProcAddressTable() {
+    if (wglExtProcAddressTable == null) {
+      // FIXME: cache ProcAddressTables by capability bits so we can
+      // share them among contexts with the same capabilities
+      wglExtProcAddressTable = new WGLExtProcAddressTable();
+    }          
+    return wglExtProcAddressTable;
+  }
+  
+  public String getPlatformExtensionsString() {
+    if (!wglGetExtensionsStringEXTInitialized) {
+      wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0);
+      wglGetExtensionsStringEXTInitialized = true;
+    }
+    if (wglGetExtensionsStringEXTAvailable) {
+      return getWGLExt().wglGetExtensionsStringEXT();
+    } else {
+      return "";
+    }
+  }
+
+  protected boolean isFunctionAvailable(String glFunctionName)
+  {
+    boolean available = super.isFunctionAvailable(glFunctionName);
+    
+    // Sanity check for implementations that use proc addresses for run-time
+    // linking: if the function IS available, then make sure there's a proc
+    // address for it if it's an extension or not part of the OpenGL 1.1 core
+    // (post GL 1.1 functions are run-time linked on windows).
+    assert(!available ||
+           (getGLProcAddressTable().getAddressFor(mapToRealGLFunctionName(glFunctionName)) != 0 ||
+            FunctionAvailabilityCache.isPartOfGLCore("1.1", mapToRealGLFunctionName(glFunctionName)))
+           );
+
+    return available;
+  }
+  
+  public void setSwapInterval(int interval) {
+    // FIXME: make the context current first? Currently assumes that
+    // will not be necessary. Make the caller do this?
+    WGLExt wglExt = getWGLExt();
+    if (wglExt.isExtensionAvailable("WGL_EXT_swap_control")) {
+      wglExt.wglSwapIntervalEXT(interval);
+    }
+  }
+
+  public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+    return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
+  }
+
+  public int getOffscreenContextPixelDataType() {
+    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");
+  }
+
+  public void bindPbufferToTexture() {
+    throw new GLException("Should not call this");
+  }
+
+  public void releasePbufferFromTexture() {
+    throw new GLException("Should not call this");
+  }
+
+  //----------------------------------------------------------------------
+  // Internals only below this point
+  //
+
+  protected long getHGLRC() {
+    return hglrc;
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawable.java
new file mode 100644
index 000000000..ae95f5505
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawable.java
@@ -0,0 +1,502 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.awt.Component;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public abstract class WindowsGLDrawable extends GLDrawableImpl {
+  protected static final boolean DEBUG = Debug.debug("WindowsGLDrawable");
+
+  protected long hdc;
+  protected Component component;
+  protected GLCapabilities capabilities;
+  protected GLCapabilitiesChooser chooser;
+  protected boolean pixelFormatChosen;
+
+  protected static final int MAX_PFORMATS = 256;
+  protected static final int MAX_ATTRIBS  = 256;
+
+  public WindowsGLDrawable(Component component,
+                           GLCapabilities capabilities,
+                           GLCapabilitiesChooser chooser) {
+    this.component = component;
+    this.capabilities = (GLCapabilities) capabilities.clone();
+    this.chooser = chooser;
+  }
+
+  public void setRealized(boolean val) {
+    throw new GLException("Should not call this (should only be called for onscreen GLDrawables)");
+  }
+
+  public void destroy() {
+    throw new GLException("Should not call this (should only be called for offscreen GLDrawables)");
+  }
+
+  public void swapBuffers() throws GLException {
+  }
+
+  public long getHDC() {
+    return hdc;
+  }
+
+  public void choosePixelFormat(boolean onscreen) {
+    PIXELFORMATDESCRIPTOR pfd = null;
+    int pixelFormat = 0;
+    if (onscreen) {
+      if (WGL.GetPixelFormat(hdc) != 0) {
+        // The Java2D/OpenGL pipeline probably already set a pixel
+        // format for this canvas.
+        if (DEBUG) {
+          System.err.println("NOTE: pixel format already chosen (by Java2D/OpenGL pipeline?) for window: " + 
+                             WGL.GetPixelFormat(hdc));
+        }
+        pixelFormatChosen = true;
+        return;
+      }
+
+      GLCapabilities[] availableCaps = null;
+      int numFormats = 0;
+      pfd = newPixelFormatDescriptor();
+      GraphicsConfiguration config = component.getGraphicsConfiguration();
+      GraphicsDevice device = config.getDevice();
+      // Produce a recommended pixel format selection for the GLCapabilitiesChooser.
+      // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available
+      WindowsGLDrawable dummyDrawable = null;
+      GLContextImpl     dummyContext  = null;
+      WGLExt            dummyWGLExt   = null;
+      if (capabilities.getSampleBuffers()) {
+        dummyDrawable = new WindowsDummyGLDrawable();
+        dummyContext  = (GLContextImpl) dummyDrawable.createContext(null);
+        if (dummyContext != null) {
+          dummyContext.makeCurrent();
+          dummyWGLExt = (WGLExt) dummyContext.getPlatformGLExtensions();
+        }
+      }      
+      int recommendedPixelFormat = -1;
+      boolean haveWGLChoosePixelFormatARB = false;
+      boolean haveWGLARBMultisample = false;
+      boolean gotAvailableCaps = false;
+      if (dummyWGLExt != null) {
+        haveWGLChoosePixelFormatARB = dummyWGLExt.isExtensionAvailable("WGL_ARB_pixel_format");
+        haveWGLARBMultisample       = dummyWGLExt.isExtensionAvailable("WGL_ARB_multisample");
+
+        try {
+          if (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++] = WGLExt.WGL_SUPPORT_OPENGL_ARB;
+            iattributes[niattribs++] = GL.GL_TRUE;
+            iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
+            iattributes[niattribs++] = GL.GL_TRUE;
+            iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
+            iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB;
+            iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
+            if (capabilities.getDoubleBuffered()) {
+              iattributes[niattribs++] = GL.GL_TRUE;
+            } else {
+              iattributes[niattribs++] = GL.GL_FALSE;
+            }
+            iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB;
+            if (capabilities.getStereo()) {
+              iattributes[niattribs++] = GL.GL_TRUE;
+            } else {
+              iattributes[niattribs++] = GL.GL_FALSE;
+            }
+            iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getDepthBits();
+            iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getRedBits();
+            iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getGreenBits();
+            iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getBlueBits();
+            iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getAlphaBits();
+            iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB;
+            iattributes[niattribs++] = capabilities.getStencilBits();
+            if (capabilities.getAccumRedBits()   > 0 ||
+                capabilities.getAccumGreenBits() > 0 ||
+                capabilities.getAccumBlueBits()  > 0 ||
+                capabilities.getAccumAlphaBits()  > 0) {
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB;
+              iattributes[niattribs++] = (capabilities.getAccumRedBits() +
+                                          capabilities.getAccumGreenBits() +
+                                          capabilities.getAccumBlueBits() +
+                                          capabilities.getAccumAlphaBits());
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB;
+              iattributes[niattribs++] = capabilities.getAccumRedBits();
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB;
+              iattributes[niattribs++] = capabilities.getAccumGreenBits();
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB;
+              iattributes[niattribs++] = capabilities.getAccumBlueBits();
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB;
+              iattributes[niattribs++] = capabilities.getAccumAlphaBits();
+            }
+            if (haveWGLARBMultisample) {
+              if (capabilities.getSampleBuffers()) {
+                iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB;
+                iattributes[niattribs++] = GL.GL_TRUE;
+                iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB;
+                iattributes[niattribs++] = capabilities.getNumSamples();
+              }
+            }
+          
+            int[] pformats = new int[MAX_PFORMATS];
+            int[] numFormatsTmp = new int[1];
+            if (dummyWGLExt.wglChoosePixelFormatARB(hdc,
+                                                    iattributes, 0,
+                                                    fattributes, 0,
+                                                    MAX_PFORMATS,
+                                                    pformats, 0,
+                                                    numFormatsTmp, 0)) {
+              numFormats = numFormatsTmp[0];
+              if (numFormats > 0) {
+                // Remove one-basing of pixel format (added on later)
+                recommendedPixelFormat = pformats[0] - 1;
+                if (DEBUG) {
+                  System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat);
+                }
+              }
+            } else {
+              if (DEBUG) {
+                System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() );
+                Thread.dumpStack();
+              }
+            }
+            if (DEBUG) {
+              if (recommendedPixelFormat < 0) {
+                System.err.print(getThreadName() + ": 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] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB;
+            if (dummyWGLExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) {
+              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++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB;
+              iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB;
+              if (haveWGLARBMultisample) {
+                iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB;
+                iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB;
+              }
+
+              availableCaps = new GLCapabilities[numFormats];
+              for (int i = 0; i < numFormats; i++) {
+                if (!dummyWGLExt.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) {
+                  throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context");
+                }
+                availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
+              }
+              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());
+              }
+            }
+          }
+        } finally {
+          dummyContext.release();
+          dummyContext.destroy();
+          dummyDrawable.destroy();
+        }
+      }
+
+      // Fallback path for older cards, in particular Intel Extreme motherboard graphics
+      if (!gotAvailableCaps) {
+        if (DEBUG) {
+          if (!capabilities.getSampleBuffers()) {
+            System.err.println(getThreadName() + ": Using ChoosePixelFormat because multisampling not requested");
+          } else {
+            System.err.println(getThreadName() + ": Using ChoosePixelFormat because no wglChoosePixelFormatARB");
+          }
+        }
+        pfd = glCapabilities2PFD(capabilities, onscreen);
+        // Remove one-basing of pixel format (added on later)
+        recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd) - 1;
+
+        numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
+        if (numFormats == 0) {
+          throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser");
+        }
+        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
+      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(getThreadName() + ": 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: " + WGL.GetLastError());
+      }
+    } 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)) {
+      int lastError = WGL.GetLastError();
+      if (DEBUG) {
+        System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() +
+                           ", current DC = " + WGL.wglGetCurrentDC());
+        System.err.println(getThreadName() + ": GetPixelFormat(hdc " + toHexString(hdc) + ") returns " + WGL.GetPixelFormat(hdc));
+      }
+      throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + toHexString(hdc) + ": error code " + lastError);
+    }
+    pixelFormatChosen = true;
+  }
+
+  static PIXELFORMATDESCRIPTOR glCapabilities2PFD(GLCapabilities caps, boolean onscreen) {
+    int colorDepth = (caps.getRedBits() +
+                      caps.getGreenBits() +
+                      caps.getBlueBits());
+    if (colorDepth < 15) {
+      throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported");
+    }
+    PIXELFORMATDESCRIPTOR pfd = newPixelFormatDescriptor();
+    int pfdFlags = (WGL.PFD_SUPPORT_OPENGL |
+                    WGL.PFD_GENERIC_ACCELERATED);
+    if (caps.getDoubleBuffered()) {
+      pfdFlags |= WGL.PFD_DOUBLEBUFFER;
+    }
+    if (onscreen) {
+      pfdFlags |= WGL.PFD_DRAW_TO_WINDOW;
+    } else {
+      pfdFlags |= WGL.PFD_DRAW_TO_BITMAP;
+    }
+    pfd.dwFlags(pfdFlags);
+    pfd.iPixelType((byte) WGL.PFD_TYPE_RGBA);
+    pfd.cColorBits((byte) colorDepth);
+    pfd.cRedBits  ((byte) caps.getRedBits());
+    pfd.cGreenBits((byte) caps.getGreenBits());
+    pfd.cBlueBits ((byte) caps.getBlueBits());
+    pfd.cAlphaBits((byte) caps.getAlphaBits());
+    int accumDepth = (caps.getAccumRedBits() +
+                      caps.getAccumGreenBits() +
+                      caps.getAccumBlueBits());
+    pfd.cAccumBits     ((byte) accumDepth);
+    pfd.cAccumRedBits  ((byte) caps.getAccumRedBits());
+    pfd.cAccumGreenBits((byte) caps.getAccumGreenBits());
+    pfd.cAccumBlueBits ((byte) caps.getAccumBlueBits());
+    pfd.cAccumAlphaBits((byte) caps.getAccumAlphaBits());
+    pfd.cDepthBits((byte) caps.getDepthBits());
+    pfd.cStencilBits((byte) caps.getStencilBits());
+    pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE);
+    return pfd;
+  }
+
+  static PIXELFORMATDESCRIPTOR newPixelFormatDescriptor() {
+    PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
+    pfd.nSize((short) pfd.size());
+    pfd.nVersion((short) 1);
+    return pfd;
+  }
+
+  static GLCapabilities pfd2GLCapabilities(PIXELFORMATDESCRIPTOR pfd) {
+    if ((pfd.dwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) {
+      return null;
+    }
+    GLCapabilities res = new GLCapabilities();
+    res.setRedBits       (pfd.cRedBits());
+    res.setGreenBits     (pfd.cGreenBits());
+    res.setBlueBits      (pfd.cBlueBits());
+    res.setAlphaBits     (pfd.cAlphaBits());
+    res.setAccumRedBits  (pfd.cAccumRedBits());
+    res.setAccumGreenBits(pfd.cAccumGreenBits());
+    res.setAccumBlueBits (pfd.cAccumBlueBits());
+    res.setAccumAlphaBits(pfd.cAccumAlphaBits());
+    res.setDepthBits     (pfd.cDepthBits());
+    res.setStencilBits   (pfd.cStencilBits());
+    res.setDoubleBuffered((pfd.dwFlags() & WGL.PFD_DOUBLEBUFFER) != 0);
+    res.setStereo        ((pfd.dwFlags() & WGL.PFD_STEREO) != 0);
+    res.setHardwareAccelerated(((pfd.dwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) ||
+			       ((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 WGLExt.WGL_DRAW_TO_WINDOW_ARB:
+          if (iresults[i] != GL.GL_TRUE)
+            return null;
+          break;
+
+        case WGLExt.WGL_ACCELERATION_ARB:
+          res.setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB);
+          break;
+
+        case WGLExt.WGL_SUPPORT_OPENGL_ARB:
+          if (iresults[i] != GL.GL_TRUE)
+            return null;
+          break;
+
+        case WGLExt.WGL_DEPTH_BITS_ARB:
+          res.setDepthBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_STENCIL_BITS_ARB:
+          res.setStencilBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_DOUBLE_BUFFER_ARB:
+          res.setDoubleBuffered(iresults[i] == GL.GL_TRUE);
+          break;
+
+        case WGLExt.WGL_STEREO_ARB:
+          res.setStereo(iresults[i] == GL.GL_TRUE);
+          break;
+
+        case WGLExt.WGL_PIXEL_TYPE_ARB:
+          if (iresults[i] != WGLExt.WGL_TYPE_RGBA_ARB)
+            return null;
+          break;
+
+        case WGLExt.WGL_RED_BITS_ARB:
+          res.setRedBits(iresults[i]);
+          break;
+          
+        case WGLExt.WGL_GREEN_BITS_ARB:
+          res.setGreenBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_BLUE_BITS_ARB:
+          res.setBlueBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_ALPHA_BITS_ARB:
+          res.setAlphaBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_ACCUM_RED_BITS_ARB:
+          res.setAccumRedBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_ACCUM_GREEN_BITS_ARB:
+          res.setAccumGreenBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_ACCUM_BLUE_BITS_ARB:
+          res.setAccumBlueBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB:
+          res.setAccumAlphaBits(iresults[i]);
+          break;
+
+        case WGLExt.WGL_SAMPLE_BUFFERS_ARB:
+          res.setSampleBuffers(iresults[i] == GL.GL_TRUE);
+          break;
+
+        case WGLExt.WGL_SAMPLES_ARB:
+          res.setNumSamples(iresults[i]);
+          break;
+
+        default:
+          throw new GLException("Unknown pixel format attribute " + iattribs[i]);
+      }
+    }
+    return res;
+  }
+
+  protected static String getThreadName() {
+    return Thread.currentThread().getName();
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawableFactory.java b/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawableFactory.java
new file mode 100644
index 000000000..ae48be999
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsGLDrawableFactory.java
@@ -0,0 +1,223 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.awt.Component;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsGLDrawableFactory extends GLDrawableFactoryImpl {
+  private static final boolean DEBUG = Debug.debug("WindowsGLDrawableFactory");
+  private static final boolean VERBOSE = Debug.verbose();
+
+  // Handle to GLU32.dll
+  // FIXME: this should go away once we delete support for the C GLU library
+  private long hglu32;
+
+  static {
+    NativeLibLoader.load();
+  }
+  
+  public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities,
+                                                           GLCapabilitiesChooser chooser,
+                                                           GraphicsDevice device) {
+    return null;
+  }
+
+  public GLDrawable getGLDrawable(Object target,
+                                  GLCapabilities capabilities,
+                                  GLCapabilitiesChooser chooser) {
+    if (target == null) {
+      throw new IllegalArgumentException("Null target");
+    }
+    if (!(target instanceof Component)) {
+      throw new IllegalArgumentException("GLDrawables not supported for objects of type " +
+                                         target.getClass().getName() + " (only Components are supported in this implementation)");
+    }
+    if (capabilities == null) {
+      capabilities = new GLCapabilities();
+    }
+    if (chooser == null) {
+      chooser = new DefaultGLCapabilitiesChooser();
+    }
+    return new WindowsOnscreenGLDrawable((Component) target, capabilities, chooser);
+  }
+
+  public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities,
+                                                GLCapabilitiesChooser chooser) {
+    return new WindowsOffscreenGLDrawable(capabilities, chooser);
+  }
+
+  private boolean pbufferSupportInitialized = false;
+  private boolean canCreateGLPbuffer = false;
+  public boolean canCreateGLPbuffer() {
+    if (!pbufferSupportInitialized) {
+      Runnable r = new Runnable() {
+          public void run() {
+            WindowsDummyGLDrawable dummyDrawable = new WindowsDummyGLDrawable();
+            GLContext dummyContext  = dummyDrawable.createContext(null);
+            if (dummyContext != null) {
+              GLContext lastContext = GLContext.getCurrent();
+              if (lastContext != null) {
+                lastContext.release();
+              }
+              dummyContext.makeCurrent();
+              GL dummyGL = dummyContext.getGL();
+              canCreateGLPbuffer = dummyGL.isExtensionAvailable("GL_ARB_pbuffer");
+              pbufferSupportInitialized = true;
+              dummyContext.release();
+              dummyContext.destroy();
+              dummyDrawable.destroy();
+              if (lastContext != null) {
+                lastContext.makeCurrent();
+              }
+            }
+          }
+        };
+      maybeDoSingleThreadedWorkaround(r);
+    }
+    return canCreateGLPbuffer;
+  }
+
+  public GLPbuffer createGLPbuffer(final GLCapabilities capabilities,
+                                   final int initialWidth,
+                                   final int initialHeight,
+                                   final GLContext shareWith) {
+    if (!canCreateGLPbuffer()) {
+      throw new GLException("Pbuffer support not available with current graphics card");
+    }
+    final List returnList = new ArrayList();
+    Runnable r = new Runnable() {
+        public void run() {
+          WindowsDummyGLDrawable dummyDrawable = new WindowsDummyGLDrawable();
+          WindowsGLContext       dummyContext  = (WindowsGLContext) dummyDrawable.createContext(null);
+          GLContext lastContext = GLContext.getCurrent();
+          if (lastContext != null) {
+            lastContext.release();
+          }
+          dummyContext.makeCurrent();
+          WGLExt dummyWGLExt = dummyContext.getWGLExt();
+          try {
+            WindowsPbufferGLDrawable pbufferDrawable = new WindowsPbufferGLDrawable(capabilities,
+                                                                                    initialWidth,
+                                                                                    initialHeight,
+                                                                                    dummyDrawable,
+                                                                                    dummyWGLExt);
+            GLPbufferImpl pbuffer = new GLPbufferImpl(pbufferDrawable, shareWith);
+            returnList.add(pbuffer);
+            dummyContext.release();
+            dummyContext.destroy();
+            dummyDrawable.destroy();
+          } finally {
+            if (lastContext != null) {
+              lastContext.makeCurrent();
+            }
+          }
+        }
+      };
+    maybeDoSingleThreadedWorkaround(r);
+    return (GLPbuffer) returnList.get(0);
+  }
+
+  public GLContext createExternalGLContext() {
+    return new WindowsExternalGLContext();
+  }
+
+  public boolean canCreateExternalGLDrawable() {
+    return true;
+  }
+
+  public GLDrawable createExternalGLDrawable() {
+    return new WindowsExternalGLDrawable();
+  }
+
+  public 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;
+  }
+
+  static String wglGetLastError() {
+    int err = WGL.GetLastError();
+    String detail = null;
+    switch (err) {
+      case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT";       break;
+      case WGL.ERROR_NO_SYSTEM_RESOURCES:  detail = "ERROR_NO_SYSTEM_RESOURCES";        break;
+      case WGL.ERROR_INVALID_DATA:         detail = "ERROR_INVALID_DATA";               break;
+      case WGL.ERROR_PROC_NOT_FOUND:       detail = "ERROR_PROC_NOT_FOUND";             break;
+      case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE";      break;
+      default:                             detail = "(Unknown error code " + err + ")"; break;
+    }
+    return detail;
+  }
+
+  private void maybeDoSingleThreadedWorkaround(Runnable action) {
+    if (Threading.isSingleThreaded() &&
+        !Threading.isOpenGLThread()) {
+      Threading.invokeOnOpenGLThread(action);
+    } else {
+      action.run();
+    }
+  }
+
+  public void lockAWTForJava2D() {
+  }
+
+  public void unlockAWTForJava2D() {
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLContext.java
new file mode 100644
index 000000000..d9430638c
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLContext.java
@@ -0,0 +1,64 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsOffscreenGLContext extends WindowsGLContext {
+  public WindowsOffscreenGLContext(WindowsOffscreenGLDrawable drawable,
+                                   GLContext shareWith) {
+    super(drawable, shareWith);
+  }
+
+  public int getOffscreenContextPixelDataType() {
+      return GL.GL_UNSIGNED_BYTE;
+  }
+  
+  public int getOffscreenContextReadBuffer() {
+    // On Windows these contexts are always single-buffered
+    return GL.GL_FRONT;
+  }
+
+  public boolean offscreenImageNeedsVerticalFlip() {
+    // We can take care of this in the DIB creation (see below)
+    return false;
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLDrawable.java
new file mode 100644
index 000000000..7dd6d2361
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsOffscreenGLDrawable.java
@@ -0,0 +1,133 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsOffscreenGLDrawable extends WindowsGLDrawable {
+  private long origbitmap;
+  private long hbitmap;
+  // Width and height of the underlying bitmap
+  private int  width;
+  private int  height;
+
+  public WindowsOffscreenGLDrawable(GLCapabilities capabilities,
+                                    GLCapabilitiesChooser chooser) {
+    super(null, capabilities, chooser);
+  }
+
+  public GLContext createContext(GLContext shareWith) {
+    return new WindowsOffscreenGLContext(this, shareWith);
+  }
+
+  public void setSize(int newWidth, int newHeight) {
+    width = newWidth;
+    height = newHeight;
+    if (hdc != 0) {
+      destroy();
+    }
+    create();
+  }
+
+  public int getWidth() {
+    return width;
+  }
+
+  public int getHeight() {
+    return height;
+  }
+  
+  private void create() {
+    BITMAPINFO info = new BITMAPINFO();
+    BITMAPINFOHEADER header = info.bmiHeader();
+    int bitsPerPixel = (capabilities.getRedBits() +
+                        capabilities.getGreenBits() +
+                        capabilities.getBlueBits());
+    header.biSize(header.size());
+    header.biWidth(width);
+    // NOTE: negating the height causes the DIB to be in top-down row
+    // order rather than bottom-up; ends up being correct during pixel
+    // readback
+    header.biHeight(-1 * height);
+    header.biPlanes((short) 1);
+    header.biBitCount((short) bitsPerPixel);
+    header.biXPelsPerMeter(0);
+    header.biYPelsPerMeter(0);
+    header.biClrUsed(0);
+    header.biClrImportant(0);
+    header.biCompression(WGL.BI_RGB);
+    header.biSizeImage(width * height * bitsPerPixel / 8);
+
+    hdc = WGL.CreateCompatibleDC(0);
+    if (hdc == 0) {
+      System.out.println("LastError: " + WGL.GetLastError());
+      throw new GLException("Error creating device context for offscreen OpenGL context");
+    }
+    hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, 0, 0, 0);
+    if (hbitmap == 0) {
+      WGL.DeleteDC(hdc);
+      hdc = 0;
+      throw new GLException("Error creating offscreen bitmap of width " + width +
+                            ", height " + height);
+    }
+    if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) {
+      WGL.DeleteObject(hbitmap);
+      hbitmap = 0;
+      WGL.DeleteDC(hdc);
+      hdc = 0;
+      throw new GLException("Error selecting bitmap into new device context");
+    }
+    
+    choosePixelFormat(false);
+  }
+  
+  public void destroy() {
+    if (hdc != 0) {
+      // Must destroy bitmap and device context
+      WGL.SelectObject(hdc, origbitmap);
+      WGL.DeleteObject(hbitmap);
+      WGL.DeleteDC(hdc);
+      origbitmap = 0;
+      hbitmap = 0;
+      hdc = 0;
+    }
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLContext.java
new file mode 100644
index 000000000..00647e7dd
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLContext.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.util.*;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsOnscreenGLContext extends WindowsGLContext {
+  protected WindowsOnscreenGLDrawable drawable;
+
+  public WindowsOnscreenGLContext(WindowsOnscreenGLDrawable drawable,
+                                  GLContext shareWith) {
+    super(drawable, shareWith);
+    this.drawable = drawable;
+  }
+  
+  protected int makeCurrentImpl() throws GLException {
+    try {
+      int lockRes = drawable.lockSurface();
+      if (lockRes == WindowsOnscreenGLDrawable.LOCK_SURFACE_NOT_READY) {
+        return CONTEXT_NOT_CURRENT;
+      }
+      if (lockRes == WindowsOnscreenGLDrawable.LOCK_SURFACE_CHANGED) {
+        if (hglrc != 0) {
+          if (!WGL.wglDeleteContext(hglrc)) {
+            throw new GLException("Unable to delete old GL context after surface changed");
+          }
+          GLContextShareSet.contextDestroyed(this);
+          if (DEBUG) {
+            System.err.println(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc) + " due to JAWT_LOCK_SURFACE_CHANGED");
+          }
+          hglrc = 0;
+        }
+      }
+      int ret = super.makeCurrentImpl();
+      return ret;
+    } catch (RuntimeException e) {
+      try {
+        drawable.unlockSurface();
+      } catch (Exception e2) {
+        // do nothing if unlockSurface throws
+      }
+      throw(e); 
+    }
+  }
+
+  protected void releaseImpl() throws GLException {
+    try {
+      super.releaseImpl();
+    } finally {
+      drawable.unlockSurface();
+    }
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLDrawable.java
new file mode 100644
index 000000000..b1f2d57a1
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsOnscreenGLDrawable.java
@@ -0,0 +1,198 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import java.awt.Component;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsOnscreenGLDrawable extends WindowsGLDrawable {
+  public static final int LOCK_SURFACE_NOT_READY = 1;
+  public static final int LOCK_SURFACE_CHANGED = 2;
+  public static final int LOCK_SUCCESS = 3;
+  private static JAWT jawt;
+
+  // Variables for lockSurface/unlockSurface
+  private JAWT_DrawingSurface ds;
+  private JAWT_DrawingSurfaceInfo dsi;
+  private 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;
+
+  public WindowsOnscreenGLDrawable(Component component,
+                                   GLCapabilities capabilities,
+                                   GLCapabilitiesChooser chooser) {
+    super(component, capabilities, chooser);
+  }
+
+  public GLContext createContext(GLContext shareWith) {
+    return new WindowsOnscreenGLContext(this, shareWith);
+  }
+
+  public void setRealized(boolean realized) {
+    this.realized = realized;
+    if (!realized) {
+      // Assume heavyweight widget was destroyed
+      pixelFormatChosen = false;
+    }
+  }
+
+  public void setSize(int width, int height) {
+    component.setSize(width, height);
+  }
+
+  public int getWidth() {
+    return component.getWidth();
+  }
+
+  public int getHeight() {
+    return component.getHeight();
+  }
+
+  public void swapBuffers() throws GLException {
+    boolean didLock = false;
+
+    if (hdc == 0) {
+      if (lockSurface() == LOCK_SURFACE_NOT_READY) {
+        return;
+      }
+      didLock = true;
+    }
+
+    if (!WGL.SwapBuffers(hdc) && (WGL.GetLastError() != 0)) {
+      throw new GLException("Error swapping buffers");
+    }
+
+    if (didLock) {
+      unlockSurface();
+    }
+  }
+
+  public int lockSurface() throws GLException {
+    if (!realized) {
+      return LOCK_SURFACE_NOT_READY;
+    }
+    if (hdc != 0) {
+      throw new GLException("Surface already locked");
+    }
+    ds = getJAWT().GetDrawingSurface(component);
+    if (ds == null) {
+      // Widget not yet realized
+      return LOCK_SURFACE_NOT_READY;
+    }
+    int res = ds.Lock();
+    if ((res & JAWTFactory.JAWT_LOCK_ERROR) != 0) {
+      throw new GLException("Unable to lock surface");
+    }
+    // See whether the surface changed and if so destroy the old
+    // OpenGL context so it will be recreated (NOTE: removeNotify
+    // should handle this case, but it may be possible that race
+    // conditions can cause this code to be triggered -- should test
+    // more)
+    int ret = LOCK_SUCCESS;
+    if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
+      ret = LOCK_SURFACE_CHANGED;
+    }
+    dsi = ds.GetDrawingSurfaceInfo();
+    if (dsi == null) {
+      // Widget not yet realized
+      ds.Unlock();
+      getJAWT().FreeDrawingSurface(ds);
+      ds = null;
+      return LOCK_SURFACE_NOT_READY;
+    }
+    win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo();
+    hdc = win32dsi.hdc();
+    if (hdc == 0) {
+      // Widget not yet realized
+      ds.FreeDrawingSurfaceInfo(dsi);
+      ds.Unlock();
+      getJAWT().FreeDrawingSurface(ds);
+      ds = null;
+      dsi = null;
+      win32dsi = null;
+      return LOCK_SURFACE_NOT_READY;
+    }
+    if (!pixelFormatChosen) {
+      choosePixelFormat(true);
+    }
+    return ret;
+  }
+
+  public void unlockSurface() {
+    if (hdc == 0) {
+      throw new GLException("Surface already unlocked");
+    }
+    ds.FreeDrawingSurfaceInfo(dsi);
+    ds.Unlock();
+    getJAWT().FreeDrawingSurface(ds);
+    ds = null;
+    dsi = null;
+    win32dsi = null;
+    hdc = 0;
+  }
+
+  //----------------------------------------------------------------------
+  // Internals only below this point
+  //
+
+  private JAWT getJAWT() {
+    if (jawt == null) {
+      JAWT j = new JAWT();
+      j.version(JAWTFactory.JAWT_VERSION_1_4);
+      if (!JAWTFactory.JAWT_GetAWT(j)) {
+        throw new RuntimeException("Unable to initialize JAWT");
+      }
+      jawt = j;
+    }
+    return jawt;
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLContext.java b/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLContext.java
new file mode 100644
index 000000000..edfc70e5f
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLContext.java
@@ -0,0 +1,163 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsPbufferGLContext extends WindowsGLContext {
+  private static final boolean DEBUG = Debug.debug("WindowsPbufferGLContext");
+
+  // State for render-to-texture and render-to-texture-rectangle support
+  private WindowsPbufferGLDrawable drawable;
+  private boolean rtt;       // render-to-texture?
+  private boolean hasRTT;    // render-to-texture extension available?
+  private boolean rect;      // render-to-texture-rectangle?
+  private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
+  private int texture;       // actual texture object
+
+  public WindowsPbufferGLContext(WindowsPbufferGLDrawable drawable,
+                                 GLContext shareWith) {
+    super(drawable, shareWith);
+    this.drawable = drawable;
+  }
+
+  public void bindPbufferToTexture() {
+    if (!rtt) {
+      throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
+                            "specified in its GLCapabilities");
+    }
+    GL gl = getGL();
+    WGLExt wglExt = getWGLExt();
+    gl.glBindTexture(textureTarget, texture);
+    if (rtt && hasRTT) {
+      if (!wglExt.wglBindTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) {
+        throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
+      }
+    }
+    // FIXME: comment is wrong now
+    // Note that if the render-to-texture extension is not supported,
+    // we perform a glCopyTexImage2D in swapBuffers().
+  }
+
+  public void releasePbufferFromTexture() {
+    if (!rtt) {
+      throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
+                            "specified in its GLCapabilities");
+    }
+    if (rtt && hasRTT) {
+      WGLExt wglExt = getWGLExt();
+      if (!wglExt.wglReleaseTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) {
+        throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
+      }
+    }
+  }
+
+  protected int makeCurrentImpl() throws GLException {
+    if (drawable.getHDC() == 0) {
+      // pbuffer not instantiated (yet?)
+      if (DEBUG) {
+        System.err.println("pbuffer not instantiated");
+      }
+      return CONTEXT_NOT_CURRENT;
+    }
+
+    int res = super.makeCurrentImpl();
+    if (DEBUG && VERBOSE) {
+      System.err.println("WindowsPbufferGLContext: super.makeCurrentImpl() = " + res);
+    }
+    if (res == CONTEXT_CURRENT_NEW) {
+      GLCapabilities capabilities = drawable.getCapabilities();
+
+      // Initialize render-to-texture support if requested
+      rtt  = capabilities.getOffscreenRenderToTexture();
+      rect = capabilities.getOffscreenRenderToTextureRectangle();
+      GL gl = getGL();
+
+      if (rtt) {
+        if (DEBUG) {
+          System.err.println("Initializing render-to-texture support");
+        }
+
+        if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) {
+          System.err.println("WindowsPbufferGLContext: WARNING: WGL_ARB_render_texture extension not " +
+                             "supported; implementing render_to_texture support using slow texture readback");
+        } else {
+          hasRTT = true;
+
+          if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) {
+            System.err.println("WindowsPbufferGLContext: WARNING: GL_NV_texture_rectangle extension not " +
+                               "supported; skipping requested render_to_texture_rectangle support for pbuffer");
+            rect = false;
+          }
+          if (rect) {
+            if (DEBUG) {
+              System.err.println("  Using render-to-texture-rectangle");
+            }
+            textureTarget = GL.GL_TEXTURE_RECTANGLE_NV;
+          } else {
+            if (DEBUG) {
+              System.err.println("  Using vanilla render-to-texture");
+            }
+            textureTarget = GL.GL_TEXTURE_2D;
+          }
+          int[] tmp = new int[1];
+          gl.glGenTextures(1, tmp, 0);
+          texture = tmp[0];
+          gl.glBindTexture(textureTarget, texture);
+          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
+          gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
+          gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
+        }
+      }
+    }
+    return res;
+  }
+
+  public int getFloatingPointMode() {
+    return drawable.getFloatingPointMode();
+  }
+
+  private static String wglGetLastError() {
+    return WindowsGLDrawableFactory.wglGetLastError();
+  }
+}
diff --git a/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLDrawable.java
new file mode 100644
index 000000000..8e660cc51
--- /dev/null
+++ b/src/classes/com/sun/opengl/impl/windows/WindowsPbufferGLDrawable.java
@@ -0,0 +1,399 @@
+/*
+ * 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 com.sun.opengl.impl.windows;
+
+import javax.media.opengl.*;
+import com.sun.opengl.impl.*;
+
+public class WindowsPbufferGLDrawable extends WindowsGLDrawable {
+  private int  initWidth;
+  private int  initHeight;
+
+  private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas,
+                               // needed to destroy pbuffer
+  private long buffer; // pbuffer handle
+  private int  width;
+  private int  height;
+
+  private int floatMode;
+
+  public WindowsPbufferGLDrawable(GLCapabilities capabilities,
+                                  int initialWidth,
+                                  int initialHeight,
+                                  WindowsGLDrawable dummyDrawable,
+                                  WGLExt wglExt) {
+    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 + "))");
+    }
+
+    if (DEBUG) {
+      System.out.println("Pbuffer caps on init: " + capabilities +
+                         (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+                         (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+                         (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+    }
+
+    createPbuffer(dummyDrawable.getHDC(), wglExt);
+  }
+
+  public GLContext createContext(GLContext shareWith) {
+    return new WindowsPbufferGLContext(this, shareWith);
+  }
+
+  public void destroy() {
+    if (hdc != 0) {
+      // Must release DC and pbuffer
+      // NOTE that since the context is not current, glGetError() can
+      // not be called here, so we skip the use of any composable
+      // pipelines (see WindowsOnscreenGLContext.makeCurrentImpl)
+      WGLExt wglExt = cachedWGLExt;
+      if (wglExt.wglReleasePbufferDCARB(buffer, hdc) == 0) {
+        throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError());
+      }
+      hdc = 0;
+      if (!wglExt.wglDestroyPbufferARB(buffer)) {
+        throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError());
+      }
+      buffer = 0;
+    }
+  }
+
+  public void setSize(int width, int height) {
+    // FIXME
+    throw new GLException("Not yet implemented");
+  }
+
+  public int getWidth() {
+    return width;
+  }
+
+  public int getHeight() {
+    return height;
+  }
+
+  public GLCapabilities getCapabilities() {
+    return capabilities;
+  }
+
+  public long getPbuffer() {
+    return buffer;
+  }
+
+  public int getFloatingPointMode() {
+    return floatMode;
+  }
+
+  public void swapBuffers() throws GLException {
+    // FIXME: this doesn't make sense any more because we don't have
+    // access to our OpenGL context here
+    /*
+    // 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.
+    if (rtt && !hasRTT) {
+      if (DEBUG) {
+        System.err.println("Copying pbuffer data to GL_TEXTURE_2D state");
+      }
+
+      GL gl = getGL();
+      gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, width, height);
+    }
+    */
+  }
+
+  private void createPbuffer(long parentHdc, WGLExt wglExt) {
+    int[]   iattributes = new int  [2*MAX_ATTRIBS];
+    float[] fattributes = new float[2*MAX_ATTRIBS];
+    int nfattribs = 0;
+    int niattribs = 0;
+
+    if (DEBUG) {
+      System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc));
+      System.out.println("Pbuffer caps: " + capabilities +
+                         (capabilities.getOffscreenRenderToTexture() ? " [rtt]" : "") +
+                         (capabilities.getOffscreenRenderToTextureRectangle() ? " [rect]" : "") +
+                         (capabilities.getOffscreenFloatingPointBuffers() ? " [float]" : ""));
+    }
+
+    boolean rtt      = capabilities.getOffscreenRenderToTexture();
+    boolean rect     = capabilities.getOffscreenRenderToTextureRectangle();
+    boolean useFloat = capabilities.getOffscreenFloatingPointBuffers();
+    boolean ati      = false;
+    
+    // Since we are trying to create a pbuffer, the pixel format we
+    // request (and subsequently use) must be "p-buffer capable".
+    iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB;
+    iattributes[niattribs++] = GL.GL_TRUE;
+
+    if (rtt && !rect) {
+      throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
+    }
+
+    if (rect) {
+      if (!wglExt.isExtensionAvailable("GL_NV_texture_rectangle")) {
+        throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
+      }
+    }
+
+    if (useFloat) {
+      if (!wglExt.isExtensionAvailable("WGL_ATI_pixel_format_float") &&
+          !wglExt.isExtensionAvailable("WGL_NV_float_buffer")) {
+        throw new GLException("Floating-point pbuffers not supported by this hardware");
+      }
+
+      // Prefer NVidia extension over ATI
+      if (wglExt.isExtensionAvailable("WGL_NV_float_buffer")) {
+        ati = false;
+        floatMode = GLPbuffer.NV_FLOAT;
+      } else {
+        ati = true;
+        floatMode = GLPbuffer.ATI_FLOAT;
+      }
+      if (DEBUG) {
+        System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension");
+      }
+    }
+
+    if (useFloat && ati) {
+      if (rtt) {
+        throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
+      } else {
+        iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
+        iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_FLOAT_ATI;
+      }
+    } else {
+      if (!rtt) {
+        // Currently we don't support non-truecolor visuals in the
+        // GLCapabilities, so we don't offer the option of making
+        // color-index pbuffers.
+        iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB;
+        iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB;
+      }
+    }
+
+    iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
+    if (capabilities.getDoubleBuffered()) {
+      iattributes[niattribs++] = GL.GL_TRUE;
+    } else {
+      iattributes[niattribs++] = GL.GL_FALSE;
+    }
+
+    iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB;
+    iattributes[niattribs++] = capabilities.getDepthBits();
+
+    iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB;
+    iattributes[niattribs++] = capabilities.getRedBits();
+
+    iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB;
+    iattributes[niattribs++] = capabilities.getGreenBits();
+
+    iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB;
+    iattributes[niattribs++] = capabilities.getBlueBits();
+
+    iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB;
+    iattributes[niattribs++] = capabilities.getAlphaBits();
+
+    iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB;
+    if (capabilities.getStencilBits() > 0) {
+      iattributes[niattribs++] = GL.GL_TRUE;
+    } else {
+      iattributes[niattribs++] = GL.GL_FALSE;
+    }
+
+    if (capabilities.getAccumRedBits()   > 0 ||
+        capabilities.getAccumGreenBits() > 0 ||
+        capabilities.getAccumBlueBits()  > 0) {
+      iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB;
+      iattributes[niattribs++] = GL.GL_TRUE;
+    }
+
+    if (useFloat && !ati) {
+      iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV;
+      iattributes[niattribs++] = GL.GL_TRUE;
+    }
+
+    if (rtt) {
+      if (useFloat) {
+        assert(!ati);
+        if (!rect) {
+          throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
+        }
+        iattributes[niattribs++] = WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
+        iattributes[niattribs++] = GL.GL_TRUE;
+      } else {
+        iattributes[niattribs++] = rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB;
+        iattributes[niattribs++] = GL.GL_TRUE;
+      }
+    }
+
+    iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB;
+    iattributes[niattribs++] = GL.GL_TRUE;
+    
+    int[] pformats = new int[MAX_PFORMATS];
+    int   nformats;
+    int[] nformatsTmp = new int[1];
+    if (!wglExt.wglChoosePixelFormatARB(parentHdc,
+                                        iattributes, 0,
+                                        fattributes, 0,
+                                        MAX_PFORMATS,
+                                        pformats, 0,
+                                        nformatsTmp, 0)) {
+      throw new GLException("pbuffer creation error: wglChoosePixelFormatARB() failed");
+    }
+    nformats = nformatsTmp[0];
+    if (nformats <= 0) {
+      throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format");
+    }
+
+    if (DEBUG) {
+      System.err.println("" + nformats + " suitable pixel formats found");
+      // query pixel format
+      iattributes[0] = WGLExt.WGL_RED_BITS_ARB;
+      iattributes[1] = WGLExt.WGL_GREEN_BITS_ARB;
+      iattributes[2] = WGLExt.WGL_BLUE_BITS_ARB;
+      iattributes[3] = WGLExt.WGL_ALPHA_BITS_ARB;
+      iattributes[4] = WGLExt.WGL_DEPTH_BITS_ARB;
+      iattributes[5] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB);
+      iattributes[6] = WGLExt.WGL_SAMPLE_BUFFERS_EXT;
+      iattributes[7] = WGLExt.WGL_SAMPLES_EXT;
+      iattributes[8] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB;
+      int[] ivalues = new int[9];
+      for (int i = 0; i < nformats; i++) {
+        if (!wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) {
+          throw new GLException("Error while querying pixel format " + pformats[i] +
+                                "'s (index " + i + "'s) capabilities for debugging");
+        }
+        System.err.print("pixel format " + pformats[i] + " (index " + i + "): ");
+        System.err.print( "r: " + ivalues[0]);
+        System.err.print(" g: " + ivalues[1]);
+        System.err.print(" b: " + ivalues[2]);
+        System.err.print(" a: " + ivalues[3]);
+        System.err.print(" depth: " + ivalues[4]);
+        System.err.print(" multisample: " + ivalues[6]);
+        System.err.print(" samples: " + ivalues[7]);
+        if (useFloat) {
+          if (ati) {
+            if (ivalues[5] == WGLExt.WGL_TYPE_RGBA_FLOAT_ATI) {
+              System.err.print(" [ati float]");
+            } else if (ivalues[5] != WGLExt.WGL_TYPE_RGBA_ARB) {
+              System.err.print(" [unknown pixel type " + ivalues[5] + "]");
+            }
+          } else {
+            if (ivalues[5] != 0) {
+              System.err.print(" [float]");
+            }
+          }
+        }
+
+        if (ivalues[8] != 0) {
+          System.err.print(" [pbuffer]");
+        }
+        System.err.println();
+      }
+    }
+
+    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;
+
+      if (rtt) {
+        iattributes[niattribs++]   = WGLExt.WGL_TEXTURE_FORMAT_ARB;
+        if (useFloat) {
+          iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV;
+        } else {
+          iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB;
+        }
+
+        iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB;
+        iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB;
+
+        iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB;
+        iattributes[niattribs++] = GL.GL_FALSE;
+
+        iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB;
+        iattributes[niattribs++] = GL.GL_FALSE;
+      }
+
+      iattributes[niattribs++] = 0;
+
+      tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes, 0);
+      ++whichFormat;
+    } while ((tmpBuffer == 0) && (whichFormat < nformats));
+
+    if (tmpBuffer == 0) {
+      throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: tried " + nformats +
+                            " pixel formats, last error was: " + wglGetLastError());
+    }
+
+    // Get the device context.
+    long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer);
+    if (tmpHdc == 0) {
+      throw new GLException("pbuffer creation error: wglGetPbufferDCARB() failed");
+    }
+
+    // Set up instance variables
+    buffer = tmpBuffer;
+    hdc    = tmpHdc;
+    cachedWGLExt = wglExt;
+
+    // Determine the actual width and height we were able to create.
+    int[] tmp = new int[1];
+    wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB,  tmp, 0 );
+    width = tmp[0];
+    wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
+    height = tmp[0];
+
+    if (DEBUG) {
+      System.err.println("Created pbuffer " + width + " x " + height);
+    }
+  }
+
+  private static String wglGetLastError() {
+    return WindowsGLDrawableFactory.wglGetLastError();
+  }
+}
-- 
cgit v1.2.3