aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/games/jogl/impl/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games/jogl/impl/windows')
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java365
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java56
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java169
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java203
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java413
5 files changed, 1206 insertions, 0 deletions
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
new file mode 100644
index 000000000..4575b6210
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.jogl.impl.windows;
+
+import java.awt.Component;
+import java.util.*;
+import net.java.games.gluegen.opengl.*; // for PROCADDRESS_VAR_PREFIX
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public abstract class WindowsGLContext extends GLContext {
+ private static JAWT jawt;
+ protected long hglrc;
+ protected long hdc;
+ private boolean wglGetExtensionsStringEXTInitialized;
+ private boolean wglGetExtensionsStringEXTAvailable;
+ private static final Map/*<String, String>*/ functionNameMap;
+ private static final Map/*<String, String>*/ extensionNameMap;
+
+ 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(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
+ super(component, capabilities, chooser);
+ }
+
+ protected GL createGL()
+ {
+ return new WindowsGLImpl(this);
+ }
+
+ 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;
+ }
+
+ protected abstract boolean isOffscreen();
+
+ public abstract int getOffscreenContextBufferedImageType();
+
+ public abstract int getOffscreenContextReadBuffer();
+
+ public abstract boolean offscreenImageNeedsVerticalFlip();
+
+ /**
+ * Creates and initializes an appropriate OpenGl context. Should only be
+ * called by {@link makeCurrent(Runnable)}.
+ */
+ protected abstract void create();
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ boolean created = false;
+ if (hglrc == 0) {
+ create();
+ if (DEBUG) {
+ System.err.println("!!! Created GL context for " + getClass().getName());
+ }
+ created = true;
+ }
+
+ if (!WGL.wglMakeCurrent(hdc, hglrc)) {
+ throw new GLException("Error making context current");
+ }
+
+ if (created) {
+ resetGLFunctionAvailability();
+ initAction.run();
+ }
+ return true;
+ }
+
+ protected synchronized void free() throws GLException {
+ if (!WGL.wglMakeCurrent(0, 0)) {
+ throw new GLException("Error freeing OpenGL context");
+ }
+ }
+
+ protected abstract void swapBuffers() throws GLException;
+
+
+ protected void resetGLFunctionAvailability() {
+ super.resetGLFunctionAvailability();
+ resetGLProcAddressTable();
+ }
+
+ protected void resetGLProcAddressTable() {
+
+ if (DEBUG) {
+ System.err.println("!!! Initializing OpenGL extension address table");
+ }
+
+ net.java.games.jogl.impl.ProcAddressTable table = getGLProcAddressTable();
+
+ // if GL is no longer an interface, we'll have to re-implement the code
+ // below so it only iterates through gl methods (a non-interface might
+ // have constructors, custom methods, etc). For now we assume all methods
+ // will be gl methods.
+ GL gl = getGL();
+
+ Class tableClass = table.getClass();
+
+ java.lang.reflect.Field[] fields = tableClass.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; ++i) {
+ String addressFieldName = fields[i].getName();
+ if (!addressFieldName.startsWith(GLEmitter.PROCADDRESS_VAR_PREFIX))
+ {
+ // not a proc address variable
+ continue;
+ }
+ int startOfMethodName = GLEmitter.PROCADDRESS_VAR_PREFIX.length();
+ String glFuncName = addressFieldName.substring(startOfMethodName);
+ try
+ {
+ java.lang.reflect.Field addressField = tableClass.getDeclaredField(addressFieldName);
+ assert(addressField.getType() == Long.TYPE);
+ // get the current value of the proc address variable in the table object
+ long oldProcAddress = addressField.getLong(table);
+ long newProcAddress = WGL.wglGetProcAddress(glFuncName);
+ /*
+ System.err.println(
+ "!!! Address=" + (newProcAddress == 0
+ ? "<NULL> "
+ : ("0x" +
+ Long.toHexString(newProcAddress))) +
+ "\tGL func: " + glFuncName);
+ */
+ // set the current value of the proc address variable in the table object
+ addressField.setLong(gl, newProcAddress);
+ } catch (Exception e) {
+ throw new GLException(
+ "Cannot get GL proc address for method \"" +
+ glFuncName + "\": Couldn't get value of field \"" + addressFieldName +
+ "\" in class " + tableClass.getName(), e);
+ }
+ }
+
+ }
+
+ public net.java.games.jogl.impl.ProcAddressTable getGLProcAddressTable() {
+ if (glProcAddressTable == null) {
+ // FIXME: cache ProcAddressTables by capability bits so we can
+ // share them among contexts with the same capabilities
+ glProcAddressTable =
+ new net.java.games.jogl.impl.ProcAddressTable();
+ }
+ return glProcAddressTable;
+ }
+
+ public String getPlatformExtensionsString() {
+ if (!wglGetExtensionsStringEXTInitialized) {
+ wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0);
+ wglGetExtensionsStringEXTInitialized = true;
+ }
+ if (wglGetExtensionsStringEXTAvailable) {
+ return gl.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;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only below this point
+ //
+
+ // Table that holds the addresses of the native C-language entry points for
+ // OpenGL functions.
+ private net.java.games.jogl.impl.ProcAddressTable glProcAddressTable;
+
+ protected JAWT getJAWT() {
+ if (jawt == null) {
+ JAWT j = new JAWT();
+ j.version(JAWTFactory.JAWT_VERSION_1_4);
+ if (!JAWTFactory.JAWT_GetAWT(j)) {
+ throw new RuntimeException("Unable to initialize JAWT");
+ }
+ jawt = j;
+ }
+ return jawt;
+ }
+
+ // Helper routine for the overridden create() to call
+ protected void choosePixelFormatAndCreateContext(boolean onscreen) {
+ PIXELFORMATDESCRIPTOR pfd = null;
+ int pixelFormat = 0;
+ if (chooser == null) {
+ // Note: this code path isn't taken any more now that the
+ // DefaultGLCapabilitiesChooser is present. However, it is being
+ // left in place for debugging purposes.
+ pfd = glCapabilities2PFD(capabilities, onscreen);
+ pixelFormat = WGL.ChoosePixelFormat(hdc, pfd);
+ if (pixelFormat == 0) {
+ throw new GLException("Unable to choose appropriate pixel format");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen pixel format from ChoosePixelFormat:");
+ PIXELFORMATDESCRIPTOR tmpPFD = new PIXELFORMATDESCRIPTOR();
+ WGL.DescribePixelFormat(hdc, pixelFormat, tmpPFD.size(), tmpPFD);
+ System.err.println(pfd2GLCapabilities(tmpPFD));
+ }
+ } else {
+ int numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null);
+ if (numFormats == 0) {
+ throw new GLException("Unable to enumerate pixel formats of window for GLCapabilitiesChooser");
+ }
+ GLCapabilities[] availableCaps = new GLCapabilities[numFormats];
+ pfd = new PIXELFORMATDESCRIPTOR();
+ 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);
+ if ((pixelFormat < 0) || (pixelFormat >= numFormats)) {
+ throw new GLException("Invalid result " + pixelFormat +
+ " from GLCapabilitiesChooser (should be between 0 and " +
+ (numFormats - 1) + ")");
+ }
+ if (DEBUG) {
+ System.err.println("Chosen pixel format (" + pixelFormat + "):");
+ System.err.println(availableCaps[pixelFormat]);
+ }
+ pixelFormat += 1; // one-base the index
+ if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
+ throw new GLException("Error re-describing the chosen pixel format");
+ }
+ }
+ if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) {
+ throw new GLException("Unable to set pixel format");
+ }
+ hglrc = WGL.wglCreateContext(hdc);
+ if (hglrc == 0) {
+ throw new GLException("Unable to create OpenGL context");
+ }
+ }
+
+ 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 = new PIXELFORMATDESCRIPTOR();
+ pfd.nSize((short) pfd.size());
+ pfd.nVersion((short) 1);
+ int pfdFlags = (WGL.PFD_SUPPORT_OPENGL |
+ WGL.PFD_GENERIC_ACCELERATED);
+ if (caps.getDoubleBuffered()) {
+ pfdFlags |= WGL.PFD_DOUBLEBUFFER;
+ if (onscreen) {
+ pfdFlags |= WGL.PFD_SWAP_EXCHANGE;
+ }
+ }
+ 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.cDepthBits((byte) caps.getDepthBits());
+ pfd.iLayerType((byte) WGL.PFD_MAIN_PLANE);
+ 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;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
new file mode 100644
index 000000000..15e622efb
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.jogl.impl.windows;
+
+import java.awt.Component;
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsGLContextFactory extends GLContextFactory {
+ public GLContext createGLContext(Component component,
+ GLCapabilities capabilities,
+ GLCapabilitiesChooser chooser) {
+ if (component != null) {
+ return new WindowsOnscreenGLContext(component, capabilities, chooser);
+ } else {
+ return new WindowsOffscreenGLContext(capabilities, chooser);
+ }
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
new file mode 100644
index 000000000..727517e63
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsOffscreenGLContext.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.jogl.impl.windows;
+
+import java.awt.image.BufferedImage;
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsOffscreenGLContext extends WindowsGLContext {
+ private long origbitmap;
+ private long hbitmap;
+ // Width and height of the underlying bitmap
+ private int width;
+ private int height;
+
+ public WindowsOffscreenGLContext(GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
+ super(null, capabilities, chooser);
+ }
+
+ protected GL createGL()
+ {
+ return new WindowsGLImpl(this);
+ }
+
+ protected boolean isOffscreen() {
+ return true;
+ }
+
+ public int getOffscreenContextBufferedImageType() {
+ if (capabilities.getAlphaBits() > 0) {
+ return BufferedImage.TYPE_INT_ARGB;
+ } else {
+ return BufferedImage.TYPE_INT_RGB;
+ }
+ }
+
+ 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;
+ }
+
+ public boolean canCreatePbufferContext() {
+ // For now say no
+ return false;
+ }
+
+ public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ throw new GLException("Not supported");
+ }
+
+ public void bindPbufferToTexture() {
+ throw new GLException("Should not call this");
+ }
+
+ public void releasePbufferFromTexture() {
+ throw new GLException("Should not call this");
+ }
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ if (pendingOffscreenResize) {
+ if (pendingOffscreenWidth != width || pendingOffscreenWidth != height) {
+ if (hglrc != 0) {
+ destroy();
+ }
+ width = pendingOffscreenWidth;
+ height = pendingOffscreenHeight;
+ pendingOffscreenResize = false;
+ }
+ }
+ return super.makeCurrent(initAction);
+ }
+
+ protected synchronized void swapBuffers() throws GLException {
+ }
+
+ protected 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);
+
+ // CreateDIBSection doesn't really need the device context if we are
+ // producing a truecolor bitmap.
+ hbitmap = WGL.CreateDIBSection(0, info, WGL.DIB_RGB_COLORS, 0, 0, 0);
+ if (hbitmap == 0) {
+ throw new GLException("Error creating offscreen bitmap");
+ }
+ hdc = WGL.CreateCompatibleDC(0);
+ if (hdc == 0) {
+ throw new GLException("Error creating device context for offscreen OpenGL context");
+ }
+ if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) {
+ throw new GLException("Error selecting bitmap into new device context");
+ }
+
+ choosePixelFormatAndCreateContext(false);
+ }
+
+ private void destroy() {
+ // Must destroy OpenGL context, bitmap and device context
+ WGL.wglDeleteContext(hglrc);
+ WGL.SelectObject(hdc, origbitmap);
+ WGL.DeleteObject(hbitmap);
+ WGL.DeleteDC(hdc);
+ hglrc = 0;
+ origbitmap = 0;
+ hbitmap = 0;
+ hdc = 0;
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
new file mode 100644
index 000000000..a5b7519cf
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.jogl.impl.windows;
+
+import java.awt.Component;
+import java.util.*;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsOnscreenGLContext extends WindowsGLContext {
+ // Variables for lockSurface/unlockSurface
+ JAWT_DrawingSurface ds;
+ JAWT_DrawingSurfaceInfo dsi;
+ JAWT_Win32DrawingSurfaceInfo win32dsi;
+
+ // Variables for pbuffer support
+ List pbuffersToInstantiate = new ArrayList();
+
+ public WindowsOnscreenGLContext(Component component, GLCapabilities capabilities, GLCapabilitiesChooser chooser) {
+ super(component, capabilities, chooser);
+ }
+
+ protected GL createGL()
+ {
+ return new WindowsGLImpl(this);
+ }
+
+ protected boolean isOffscreen() {
+ return false;
+ }
+
+ public int getOffscreenContextBufferedImageType() {
+ throw new GLException("Should not call this");
+ }
+
+ public int getOffscreenContextReadBuffer() {
+ throw new GLException("Should not call this");
+ }
+
+ public boolean offscreenImageNeedsVerticalFlip() {
+ throw new GLException("Should not call this");
+ }
+
+ public boolean canCreatePbufferContext() {
+ return true;
+ }
+
+ public synchronized GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ WindowsPbufferGLContext ctx = new WindowsPbufferGLContext(capabilities, initialWidth, initialHeight);
+ pbuffersToInstantiate.add(ctx);
+ return ctx;
+ }
+
+ public void bindPbufferToTexture() {
+ throw new GLException("Should not call this");
+ }
+
+ public void releasePbufferFromTexture() {
+ throw new GLException("Should not call this");
+ }
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ try {
+ if (!lockSurface()) {
+ return false;
+ }
+ boolean ret = super.makeCurrent(initAction);
+ if (ret) {
+ // Instantiate any pending pbuffers
+ while (!pbuffersToInstantiate.isEmpty()) {
+ WindowsPbufferGLContext ctx =
+ (WindowsPbufferGLContext) pbuffersToInstantiate.remove(pbuffersToInstantiate.size() - 1);
+ ctx.createPbuffer(hdc, hglrc);
+ }
+ }
+ return ret;
+ } catch (RuntimeException e) {
+ try {
+ unlockSurface();
+ } catch (Exception e2) {
+ // do nothing if unlockSurface throws
+ }
+ throw(e);
+ }
+ }
+
+ protected synchronized void free() throws GLException {
+ try {
+ super.free();
+ } finally {
+ unlockSurface();
+ }
+ }
+
+ protected synchronized void swapBuffers() throws GLException {
+ if (!WGL.SwapBuffers(hdc)) {
+ throw new GLException("Error swapping buffers");
+ }
+ }
+
+ private boolean lockSurface() throws GLException {
+ if (hdc != 0) {
+ throw new GLException("Surface already locked");
+ }
+ ds = getJAWT().GetDrawingSurface(component);
+ if (ds == null) {
+ // Widget not yet realized
+ return false;
+ }
+ 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
+ if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) {
+ if (hglrc != 0) {
+ if (!WGL.wglDeleteContext(hglrc)) {
+ throw new GLException("Unable to delete old GL context after surface changed");
+ }
+ hglrc = 0;
+ }
+ }
+ dsi = ds.GetDrawingSurfaceInfo();
+ if (dsi == null) {
+ // Widget not yet realized
+ ds.Unlock();
+ getJAWT().FreeDrawingSurface(ds);
+ ds = null;
+ return false;
+ }
+ 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 false;
+ }
+ return true;
+ }
+
+ private 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;
+ }
+
+ protected void create() {
+ choosePixelFormatAndCreateContext(true);
+ }
+}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
new file mode 100644
index 000000000..300e9cb85
--- /dev/null
+++ b/src/net/java/games/jogl/impl/windows/WindowsPbufferGLContext.java
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Sun gratefully acknowledges that this software was originally authored
+ * and developed by Kenneth Bradley Russell and Christopher John Kline.
+ */
+
+package net.java.games.jogl.impl.windows;
+
+import net.java.games.jogl.*;
+import net.java.games.jogl.impl.*;
+
+public class WindowsPbufferGLContext extends WindowsGLContext {
+ private static final boolean DEBUG = false;
+
+ private int initWidth;
+ private int initHeight;
+
+ private long buffer; // pbuffer handle
+ private int width;
+ private int height;
+
+ // FIXME: kept around because we create the OpenGL context lazily to
+ // better integrate with the WindowsGLContext framework
+ private long parentHglrc;
+
+ private static final int MAX_PFORMATS = 256;
+ private static final int MAX_ATTRIBS = 256;
+
+ // State for render-to-texture and render-to-texture-rectangle support
+ private boolean created;
+ private boolean rtt; // render-to-texture?
+ 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(GLCapabilities capabilities, int initialWidth, int initialHeight) {
+ super(null, capabilities, null);
+ this.initWidth = initialWidth;
+ this.initHeight = initialHeight;
+ if (initWidth <= 0 || initHeight <= 0) {
+ throw new GLException("Initial width and height of pbuffer must be positive (were (" +
+ initWidth + ", " + initHeight + "))");
+ }
+ }
+
+ public boolean canCreatePbufferContext() {
+ return false;
+ }
+
+ public GLContext createPbufferContext(GLCapabilities capabilities,
+ int initialWidth,
+ int initialHeight) {
+ throw new GLException("Not supported");
+ }
+
+ public void bindPbufferToTexture() {
+ 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();
+ gl.glBindTexture(textureTarget, texture);
+ // Note: this test was on the rtt variable in NVidia's code but I
+ // think it doesn't make sense written that way
+ if (rect) {
+ if (!gl.wglBindTexImageARB(buffer, GL.WGL_FRONT_LEFT_ARB)) {
+ throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
+ }
+ }
+ // Note that if the render-to-texture-rectangle extension is not
+ // specified, 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 (rect) {
+ GL gl = getGL();
+ if (!gl.wglReleaseTexImageARB(buffer, GL.WGL_FRONT_LEFT_ARB)) {
+ throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
+ }
+ }
+ }
+
+ public void createPbuffer(long parentHdc, long parentHglrc) {
+ GL gl = getGL();
+
+ int[] iattributes = new int [2*MAX_ATTRIBS];
+ float[] fattributes = new float[2*MAX_ATTRIBS];
+ int nfattribs = 0;
+ int niattribs = 0;
+
+ rtt = capabilities.getOffscreenRenderToTexture();
+ rect = capabilities.getOffscreenRenderToTextureRectangle();
+ boolean useFloat = capabilities.getOffscreenFloatingPointBuffers();
+
+ // Since we are trying to create a pbuffer, the pixel format we
+ // request (and subsequently use) must be "p-buffer capable".
+ iattributes[niattribs++] = GL.WGL_DRAW_TO_PBUFFER_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+
+ 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++] = GL.WGL_PIXEL_TYPE_ARB;
+ iattributes[niattribs++] = GL.WGL_TYPE_RGBA_ARB;
+ }
+
+ iattributes[niattribs++] = GL.WGL_DOUBLE_BUFFER_ARB;
+ if (capabilities.getDoubleBuffered()) {
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getDepthBits();
+
+ iattributes[niattribs++] = GL.WGL_RED_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getRedBits();
+
+ iattributes[niattribs++] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getGreenBits();
+
+ iattributes[niattribs++] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getBlueBits();
+
+ iattributes[niattribs++] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[niattribs++] = capabilities.getAlphaBits();
+
+ iattributes[niattribs++] = GL.WGL_STENCIL_BITS_ARB;
+ 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++] = GL.WGL_ACCUM_BITS_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+
+ if (useFloat) {
+ iattributes[niattribs++] = GL.WGL_FLOAT_COMPONENTS_NV;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+
+ if (rtt) {
+ if (useFloat) {
+ iattributes[niattribs++] = GL.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ } else {
+ iattributes[niattribs++] = rect ? GL.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : GL.WGL_BIND_TO_TEXTURE_RGB_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+ }
+ }
+
+ iattributes[niattribs++] = GL.WGL_SUPPORT_OPENGL_ARB;
+ iattributes[niattribs++] = GL.GL_TRUE;
+
+ int[] pformats = new int[MAX_PFORMATS];
+ int nformats;
+ int[] nformatsTmp = new int[1];
+ if (!gl.wglChoosePixelFormatARB(parentHdc,
+ iattributes,
+ fattributes,
+ MAX_PFORMATS,
+ pformats,
+ nformatsTmp)) {
+ 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] = GL.WGL_RED_BITS_ARB;
+ iattributes[1] = GL.WGL_GREEN_BITS_ARB;
+ iattributes[2] = GL.WGL_BLUE_BITS_ARB;
+ iattributes[3] = GL.WGL_ALPHA_BITS_ARB;
+ iattributes[4] = GL.WGL_DEPTH_BITS_ARB;
+ iattributes[5] = GL.WGL_FLOAT_COMPONENTS_NV;
+ iattributes[6] = GL.WGL_SAMPLE_BUFFERS_EXT;
+ iattributes[7] = GL.WGL_SAMPLES_EXT;
+ int[] ivalues = new int[8];
+ for (int i = 0; i < nformats; i++) {
+ if (!gl.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 8, iattributes, ivalues)) {
+ 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 (ivalues[5] != 0) {
+ System.err.print(" [float]");
+ }
+ System.err.println();
+ }
+ }
+
+ int format = pformats[0];
+
+ // Create the p-buffer.
+ niattribs = 0;
+
+ if (rtt) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FORMAT_ARB;
+ if (useFloat) {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_FLOAT_RGB_NV;
+ } else {
+ iattributes[niattribs++] = GL.WGL_TEXTURE_RGBA_ARB;
+ }
+
+ iattributes[niattribs++] = GL.WGL_TEXTURE_TARGET_ARB;
+ iattributes[niattribs++] = rect ? GL.WGL_TEXTURE_RECTANGLE_NV : GL.WGL_TEXTURE_2D_ARB;
+
+ iattributes[niattribs++] = GL.WGL_MIPMAP_TEXTURE_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
+
+ iattributes[niattribs++] = GL.WGL_PBUFFER_LARGEST_ARB;
+ iattributes[niattribs++] = GL.GL_FALSE;
+ }
+
+ iattributes[niattribs++] = 0;
+
+ long tmpBuffer = gl.wglCreatePbufferARB(parentHdc, format, initWidth, initHeight, iattributes);
+ if (tmpBuffer == 0) {
+ throw new GLException("pbuffer creation error: wglCreatePbufferARB() failed: " + wglGetLastError());
+ }
+
+ // Get the device context.
+ long tmpHdc = gl.wglGetPbufferDCARB(tmpBuffer);
+ if (tmpHdc == 0) {
+ throw new GLException("pbuffer creation error: wglGetPbufferDCARB() failed");
+ }
+
+ this.parentHglrc = parentHglrc;
+
+ // Set up instance variables
+ buffer = tmpBuffer;
+ hdc = tmpHdc;
+
+ // Determine the actual width and height we were able to create.
+ int[] tmp = new int[1];
+ gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_WIDTH_ARB, tmp );
+ width = tmp[0];
+ gl.wglQueryPbufferARB( buffer, GL.WGL_PBUFFER_HEIGHT_ARB, tmp );
+ height = tmp[0];
+
+ if (DEBUG) {
+ System.err.println("Created pbuffer " + width + " x " + height);
+ }
+ }
+
+ protected synchronized boolean makeCurrent(Runnable initAction) throws GLException {
+ created = false;
+
+ if (buffer == 0) {
+ // pbuffer not instantiated yet
+ return false;
+ }
+
+ boolean res = super.makeCurrent(initAction);
+ if (created) {
+ // Initialize render-to-texture support if requested
+ rtt = capabilities.getOffscreenRenderToTexture();
+ rect = capabilities.getOffscreenRenderToTextureRectangle();
+
+ if (rtt) {
+ if (DEBUG) {
+ System.err.println("Initializing render-to-texture support");
+ }
+
+ GL gl = getGL();
+ 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);
+ 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, width, height, 0);
+ }
+ }
+ return res;
+ }
+
+ public void handleModeSwitch(long parentHdc, long parentHglrc) {
+ throw new GLException("Not yet implemented");
+ }
+
+ protected boolean isOffscreen() {
+ // FIXME: currently the only caller of this won't cause proper
+ // resizing of the pbuffer anyway.
+ return false;
+ }
+
+ public int getOffscreenContextBufferedImageType() {
+ throw new GLException("Should not call this");
+ }
+
+ public int getOffscreenContextReadBuffer() {
+ throw new GLException("Should not call this");
+ }
+
+ public boolean offscreenImageNeedsVerticalFlip() {
+ throw new GLException("Should not call this");
+ }
+
+ protected void create() {
+ created = true;
+ // Create a gl context for the p-buffer.
+ hglrc = WGL.wglCreateContext(hdc);
+ if (hglrc == 0) {
+ throw new GLException("pbuffer creation error: wglCreateContext() failed");
+ }
+
+ // FIXME: provide option to not share display lists with subordinate pbuffer?
+ if (!WGL.wglShareLists(parentHglrc, hglrc)) {
+ throw new GLException("pbuffer: wglShareLists() failed");
+ }
+ }
+
+ protected void swapBuffers() throws GLException {
+ // FIXME: do we need to do anything if the pbuffer is double-buffered?
+ // For now, just grab the pixels for the render-to-texture support.
+ if (rtt && !rect) {
+ if (DEBUG) {
+ System.err.println("Copying pbuffer data to GL_TEXTURE_2D state");
+ }
+
+ GL gl = getGL();
+ gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, width, height, 0);
+ }
+ }
+
+ private 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;
+ }
+}