diff options
Diffstat (limited to 'src/classes/com/sun/opengl/impl/windows')
13 files changed, 2521 insertions, 7 deletions
diff --git a/src/classes/com/sun/opengl/impl/windows/awt/WindowsJAWTWindow.java b/src/classes/com/sun/opengl/impl/windows/awt/WindowsJAWTWindow.java index 68ef2702b..bebd1e4dc 100644 --- a/src/classes/com/sun/opengl/impl/windows/awt/WindowsJAWTWindow.java +++ b/src/classes/com/sun/opengl/impl/windows/awt/WindowsJAWTWindow.java @@ -47,22 +47,116 @@ import com.sun.opengl.impl.*; public class WindowsJAWTWindow extends JAWTWindow { - // Variables for lockSurface/unlockSurface - //private JAWT_DrawingSurface ds; - //private JAWT_DrawingSurfaceInfo dsi; - //private JAWT_WindowsDrawingSurfaceInfo x11dsi; - + public static final boolean PROFILING = false; // FIXME + public static final int PROFILING_TICKS = 600; // FIXME + public WindowsJAWTWindow(Object comp) { super(comp); } + protected void initNative() throws NativeWindowException { + } + public int lockSurface() throws NativeWindowException { - super.lockSurface(); - return 0; + int ret = super.lockSurface(); + if(LOCK_SUCCESS != ret) { + return ret; + } + + long startTime; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + ds = JAWT.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) + if ((res & JAWTFactory.JAWT_LOCK_SURFACE_CHANGED) != 0) { + ret = LOCK_SURFACE_CHANGED; + } + dsi = ds.GetDrawingSurfaceInfo(); + if (dsi == null) { + // Widget not yet realized + ds.Unlock(); + JAWT.getJAWT().FreeDrawingSurface(ds); + ds = null; + return LOCK_SURFACE_NOT_READY; + } + win32dsi = (JAWT_Win32DrawingSurfaceInfo) dsi.platformInfo(); + drawable = win32dsi.hdc(); + // FIXME: Are the followup abstractions available ? would it be usefull ? + display = 0; + visualID = 0; + screen= 0; + screenIndex = 0; + + if (drawable == 0) { + // Widget not yet realized + ds.FreeDrawingSurfaceInfo(dsi); + ds.Unlock(); + JAWT.getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + win32dsi = null; + return LOCK_SURFACE_NOT_READY; + } + if (PROFILING) { + long endTime = System.currentTimeMillis(); + profilingLockSurfaceTime += (endTime - startTime); + if (++profilingLockSurfaceTicks == PROFILING_TICKS) { + System.err.println("LockSurface calls: " + profilingLockSurfaceTime + " ms / " + PROFILING_TICKS + " calls (" + + ((float) profilingLockSurfaceTime / (float) PROFILING_TICKS) + " ms/call)"); + profilingLockSurfaceTime = 0; + profilingLockSurfaceTicks = 0; + } + } + return ret; } public void unlockSurface() { + if(!isSurfaceLocked()) return; + long startTime = 0; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + ds.FreeDrawingSurfaceInfo(dsi); + ds.Unlock(); + JAWT.getJAWT().FreeDrawingSurface(ds); + ds = null; + dsi = null; + win32dsi = null; + drawable = 0; super.unlockSurface(); + if (PROFILING) { + long endTime = System.currentTimeMillis(); + profilingUnlockSurfaceTime += (endTime - startTime); + if (++profilingUnlockSurfaceTicks == PROFILING_TICKS) { + System.err.println("UnlockSurface calls: " + profilingUnlockSurfaceTime + " ms / " + PROFILING_TICKS + " calls (" + + ((float) profilingUnlockSurfaceTime / (float) PROFILING_TICKS) + " ms/call)"); + profilingUnlockSurfaceTime = 0; + profilingUnlockSurfaceTicks = 0; + } + } } + + // Variables for lockSurface/unlockSurface + private JAWT_DrawingSurface ds; + private JAWT_DrawingSurfaceInfo dsi; + private JAWT_Win32DrawingSurfaceInfo win32dsi; + private long profilingLockSurfaceTime = 0; + private int profilingLockSurfaceTicks = 0; + private long profilingUnlockSurfaceTime = 0; + private int profilingUnlockSurfaceTicks = 0; + } diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java new file mode 100644 index 000000000..5324a0c55 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java @@ -0,0 +1,100 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { + private long hwnd, hdc; + + public WindowsDummyWGLDrawable(GLDrawableFactory factory) { + super(factory, new NullWindow(), true, new GLCapabilities(), null); + // All entries to CreateDummyWindow must synchronize on one object + // to avoid accidentally registering the dummy window class twice + synchronized (WindowsDummyWGLDrawable.class) { + hwnd = WGL.CreateDummyWindow(0, 0, 1, 1); + } + hdc = WGL.GetDC(hwnd); + NullWindow nw = (NullWindow) getNativeWindow(); + nw.setWindowHandle(hdc); + // 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; + } + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + return new WindowsWGLContext(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/wgl/WindowsExternalWGLContext.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsExternalWGLContext.java new file mode 100755 index 000000000..493b38061 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsExternalWGLContext.java @@ -0,0 +1,102 @@ +/* + * 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.wgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsExternalWGLContext extends WindowsWGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + public WindowsExternalWGLContext() { + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + super(null, null); + hglrc = WGL.wglGetCurrentContext(); + if (hglrc == 0) { + throw new GLException("Error: attempted to make an external GLContext without a drawable/context current"); + } + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(hglrc) + " for " + this); + } + GLContextShareSet.contextCreated(this); + resetGLFunctionAvailability(); + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + 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/wgl/WindowsExternalWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java new file mode 100755 index 000000000..2c89e1dd0 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java @@ -0,0 +1,79 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { + + public WindowsExternalWGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, true, new GLCapabilities(), null); + } + + public static WindowsExternalWGLDrawable create(GLDrawableFactory factory) { + long hdc = WGL.wglGetCurrentDC(); + NullWindow nw = new NullWindow(); + nw.setWindowHandle(hdc); + if (nw.getWindowHandle() == 0) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current"); + } + return new WindowsExternalWGLDrawable(factory, nw); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsWGLContext(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/wgl/WindowsOffscreenWGLContext.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java new file mode 100644 index 000000000..9f0a5d2a6 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsOffscreenWGLContext extends WindowsWGLContext { + public WindowsOffscreenWGLContext(WindowsOffscreenWGLDrawable 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/wgl/WindowsOffscreenWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java new file mode 100644 index 000000000..84928ae6c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java @@ -0,0 +1,138 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsOffscreenWGLDrawable extends WindowsWGLDrawable { + private long origbitmap; + private long hbitmap; + + public WindowsOffscreenWGLDrawable(GLDrawableFactory factory, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + super(factory, new NullWindow(), true, capabilities, chooser); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOffscreenWGLContext(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + super.setSize(newWidth, newHeight); + destroy(); + create(); + } + + private void create() { + getFactory().lockToolkit(); + try { + NullWindow nw = (NullWindow) getNativeWindow(); + GLCapabilities capabilities = getCapabilities(); + int width = getWidth(); + int height = getHeight(); + BITMAPINFO info = BITMAPINFO.create(); + 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); + + long hdc = WGL.CreateCompatibleDC(0); + if (hdc == 0) { + System.out.println("LastError: " + WGL.GetLastError()); + throw new GLException("Error creating device context for offscreen OpenGL context"); + } + nw.setWindowHandle(hdc); + + 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); + } finally { + getFactory().unlockToolkit(); + } + } + + public void destroy() { + getFactory().lockToolkit(); + try { + NullWindow nw = (NullWindow) getNativeWindow(); + if (nw.getWindowHandle() != 0) { + // Must destroy bitmap and device context + WGL.SelectObject(nw.getWindowHandle(), origbitmap); + WGL.DeleteObject(hbitmap); + WGL.DeleteDC(nw.getWindowHandle()); + origbitmap = 0; + hbitmap = 0; + nw.setWindowHandle(0); + setChosenGLCapabilities(null); + } + } finally { + getFactory().unlockToolkit(); + } + } +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java new file mode 100644 index 000000000..02459f590 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java @@ -0,0 +1,88 @@ +/* + * 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.wgl; + +import java.util.*; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsOnscreenWGLContext extends WindowsWGLContext { + protected WindowsOnscreenWGLDrawable drawable; + + public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + if (lockRes == NativeWindow.LOCK_SURFACE_CHANGED) { + destroyImpl(); + } + int ret = super.makeCurrentImpl(); + return ret; + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY)) { + drawable.unlockSurface(); + } + } + } + + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable()) { + drawable.unlockSurface(); + } + } + } +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java new file mode 100644 index 000000000..767928f16 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java @@ -0,0 +1,113 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable { + private static final boolean PROFILING = Debug.debug("WindowsOnscreenWGLDrawable.profiling"); + private static final int PROFILING_TICKS = 200; + private int profilingLockSurfaceTicks; + private long profilingLockSurfaceTime; + private int profilingUnlockSurfaceTicks; + private long profilingUnlockSurfaceTime; + private int profilingSwapBuffersTicks; + private long profilingSwapBuffersTime; + + protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeWindow component, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + super(factory, component, false, capabilities, chooser); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOnscreenWGLContext(this, shareWith); + } + + 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 (getNativeWindow().getWindowHandle() == 0) { + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + + long startTime = 0; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + + if (!WGL.SwapBuffers(getNativeWindow().getWindowHandle()) && (WGL.GetLastError() != 0)) { + throw new GLException("Error swapping buffers"); + } + + if (PROFILING) { + long endTime = System.currentTimeMillis(); + profilingSwapBuffersTime += (endTime - startTime); + int ticks = PROFILING_TICKS; + if (++profilingSwapBuffersTicks == ticks) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + ticks + " calls (" + + ((float) profilingSwapBuffersTime / (float) ticks) + " ms/call)"); + profilingSwapBuffersTime = 0; + profilingSwapBuffersTicks = 0; + } + } + + if (didLock) { + unlockSurface(); + } + } + +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java new file mode 100644 index 000000000..7af3cbfc9 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java @@ -0,0 +1,155 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsPbufferWGLContext extends WindowsWGLContext { + private static final boolean DEBUG = Debug.debug("WindowsPbufferWGLContext"); + + // State for render-to-texture and render-to-texture-rectangle support + private WindowsPbufferWGLDrawable 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 WindowsPbufferWGLContext(WindowsPbufferWGLDrawable 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 { + int res = super.makeCurrentImpl(); + if (DEBUG && VERBOSE) { + System.err.println("WindowsPbufferWGLContext: super.makeCurrentImpl() = " + res); + } + if (res == CONTEXT_CURRENT_NEW) { + GLCapabilities capabilities = drawable.getCapabilities(); + + // Initialize render-to-texture support if requested + GL gl = getGL(); + rtt = capabilities.getPbufferRenderToTexture(); + rect = gl.isGL2() && capabilities.getPbufferRenderToTextureRectangle(); + + if (rtt) { + if (DEBUG) { + System.err.println("Initializing render-to-texture support"); + } + + if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) { + System.err.println("WindowsPbufferWGLContext: 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("WindowsPbufferWGLContext: 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 = GL2.GL_TEXTURE_RECTANGLE_EXT; + } 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 WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java new file mode 100644 index 000000000..a7af86001 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -0,0 +1,343 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { + private long cachedParentHdc; + private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas, + // needed to destroy pbuffer + private long buffer; // pbuffer handle + + private int floatMode; + + public WindowsPbufferWGLDrawable(GLDrawableFactory factory, + GLCapabilities capabilities, + int initialWidth, + int initialHeight, + WindowsWGLDrawable dummyDrawable, + WGLExt wglExt) { + super(factory, new NullWindow(), true, capabilities, null); + if (initialWidth <= 0 || initialHeight <= 0) { + throw new GLException("Initial width and height of pbuffer must be positive (were (" + + initialWidth + ", " + initialHeight + "))"); + } + NullWindow nw = (NullWindow) getNativeWindow(); + nw.setSize(initialWidth, initialHeight); + + if (DEBUG) { + System.out.println("Pbuffer caps on init: " + capabilities + + (capabilities.getPbufferRenderToTexture() ? " [rtt]" : "") + + (capabilities.getPbufferRenderToTextureRectangle() ? " [rect]" : "") + + (capabilities.getPbufferFloatingPointBuffers() ? " [float]" : "")); + } + + createPbuffer(dummyDrawable.getNativeWindow().getWindowHandle(), wglExt); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsPbufferWGLContext(this, shareWith); + } + + public void destroy() { + getFactory().lockToolkit(); + try { + NullWindow nw = (NullWindow) getNativeWindow(); + if (nw.getWindowHandle() != 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 WindowsOnscreenWGLContext.makeCurrentImpl) + WGLExt wglExt = cachedWGLExt; + if (wglExt.wglReleasePbufferDCARB(buffer, nw.getWindowHandle()) == 0) { + throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError()); + } + nw.setWindowHandle(0); + if (!wglExt.wglDestroyPbufferARB(buffer)) { + throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError()); + } + buffer = 0; + setChosenGLCapabilities(null); + } + } finally { + getFactory().unlockToolkit(); + } + } + + public void setSize(int newWidth, int newHeight) { + super.setSize(newWidth, newHeight); + destroy(); + if(cachedParentHdc!=0 && cachedWGLExt!=null) { + createPbuffer(cachedParentHdc, cachedWGLExt); + } + } + + 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[1]; + int[] floatModeTmp = new int[1]; + int niattribs = 0; + int width, height; + + GLCapabilities capabilities = getCapabilities(); + + if (DEBUG) { + System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc)); + System.out.println("Pbuffer caps: " + capabilities + + (capabilities.getPbufferRenderToTexture() ? " [rtt]" : "") + + (capabilities.getPbufferRenderToTextureRectangle() ? " [rect]" : "") + + (capabilities.getPbufferFloatingPointBuffers() ? " [float]" : "")); + } + + getFactory().lockToolkit(); + try { + if (!glCapabilities2iattributes(capabilities, + iattributes, + wglExt, + true, + floatModeTmp)) { + throw new GLException("Pbuffer-related extensions not supported"); + } + + floatMode = floatModeTmp[0]; + boolean rtt = capabilities.getPbufferRenderToTexture(); + boolean rect = capabilities.getPbufferRenderToTextureRectangle(); + boolean useFloat = capabilities.getPbufferFloatingPointBuffers(); + boolean ati = false; + + if (useFloat) { + ati = (floatMode == GLPbuffer.ATI_FLOAT); + } + + 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"); + } + + boolean haveMultisample = wglExt.isExtensionAvailable("WGL_ARB_multisample"); + + 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] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[7] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + 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]); + if (haveMultisample) { + 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 = -1; + // Loop is a workaround for bugs in NVidia's recent drivers + for (whichFormat = 0; whichFormat < nformats; whichFormat++) { + 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, getWidth(), getHeight(), iattributes, 0); + if (tmpBuffer != 0) { + // Done + break; + } + } + + 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"); + } + + NullWindow nw = (NullWindow) getNativeWindow(); + // Set up instance variables + buffer = tmpBuffer; + nw.setWindowHandle(tmpHdc); + cachedWGLExt = wglExt; + cachedParentHdc = parentHdc; + + // Re-query chosen pixel format + { + niattribs = 0; + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_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_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_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; + iattributes[niattribs++] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + int[] ivalues = new int[niattribs]; + // FIXME: usually prefer to throw exceptions, but failure here is not critical + if (wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[whichFormat], 0, niattribs, iattributes, 0, ivalues, 0)) { + setChosenGLCapabilities(iattributes2GLCapabilities(iattributes, niattribs, ivalues, false)); + } + } + + // 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]; + nw.setSize(width, height); + } finally { + getFactory().unlockToolkit(); + } + + if (DEBUG) { + System.err.println("Created pbuffer " + width + " x " + height); + } + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLContext.java new file mode 100644 index 000000000..c6676d36d --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -0,0 +1,300 @@ +/* + * 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.wgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public class WindowsWGLContext extends GLContextImpl { + protected WindowsWGLDrawable 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"); + } + + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + public WindowsWGLContext(WindowsWGLDrawable drawable, + GLContext shareWith) { + super(shareWith); + } + + 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.getNativeWindow().getWindowHandle() == 0) { + throw new GLException("Internal error: attempted to create OpenGL context without an associated drawable"); + } + hglrc = WGL.wglCreateContext(drawable.getNativeWindow().getWindowHandle()); + if (hglrc == 0) { + throw new GLException("Unable to create OpenGL context for device context " + toHexString(drawable.getNativeWindow().getWindowHandle())); + } + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created OpenGL context " + toHexString(hglrc) + " for " + this + ", device context " + toHexString(drawable.getNativeWindow().getWindowHandle()) + ", not yet sharing"); + } + // Windows can set up sharing of display lists after creation time + WindowsWGLContext other = (WindowsWGLContext) 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.getNativeWindow().getWindowHandle()) + ", sharing with " + toHexString(hglrc2)); + } + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getNativeWindow().getWindowHandle() == 0) { + if (DEBUG) { + System.err.println("drawable not properly initialized"); + } + return CONTEXT_NOT_CURRENT; + } + boolean created = false; + if (hglrc == 0) { + create(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + created = true; + } + + if (WGL.wglGetCurrentContext() != hglrc) { + if (!WGL.wglMakeCurrent(drawable.getNativeWindow().getWindowHandle(), hglrc)) { + throw new GLException("Error making context current: " + WGL.GetLastError()); + } else { + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getNativeWindow().getWindowHandle()) + + ", 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); + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getHGLRC(); + long src = ((WindowsWGLContext) source).getHGLRC(); + if (src == 0) { + throw new GLException("Source OpenGL context has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL context has not been created"); + } + if (!WGL.wglCopyContext(src, dst, mask)) { + throw new GLException("wglCopyContext failed"); + } + } + + protected void resetGLFunctionAvailability() { + super.resetGLFunctionAvailability(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this); + } + if (wglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + wglExtProcAddressTable = new WGLExtProcAddressTable(); + } + resetProcAddressTable(getWGLExtProcAddressTable()); + } + + public final WGLExtProcAddressTable getWGLExtProcAddressTable() { + return wglExtProcAddressTable; + } + + public String getPlatformExtensionsString() { + if (!wglGetExtensionsStringEXTInitialized) { + wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0); + wglGetExtensionsStringEXTInitialized = true; + } + if (wglGetExtensionsStringEXTAvailable) { + return getWGLExt().wglGetExtensionsStringEXT(); + } else { + return ""; + } + } + + public 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). + /* FIXME: + 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 + // + + public long getHGLRC() { + return hglrc; + } +} diff --git a/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLDrawable.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLDrawable.java new file mode 100644 index 000000000..1b1805e91 --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLDrawable.java @@ -0,0 +1,662 @@ +/* + * 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.wgl; + +import javax.media.opengl.*; +import com.sun.opengl.impl.*; + +public abstract class WindowsWGLDrawable extends GLDrawableImpl { + protected static final boolean DEBUG = Debug.debug("WindowsWGLDrawable"); + + protected GLCapabilitiesChooser chooser; + protected boolean pixelFormatChosen; + + // Workaround for problems on Intel 82855 cards + private int setPixelFormatFailCount; + private static final int MAX_SET_PIXEL_FORMAT_FAIL_COUNT = 5; + + protected static final int MAX_PFORMATS = 256; + protected static final int MAX_ATTRIBS = 256; + + public WindowsWGLDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + super(factory, comp, realized); + setChosenGLCapabilities(capabilities); + this.chooser = chooser; + } + + public int lockSurface() throws GLException { + int ret = super.lockSurface(); + if(NativeWindow.LOCK_SURFACE_NOT_READY == ret) { + return ret; + } + if (!pixelFormatChosen) { + try { + choosePixelFormat(true); + setPixelFormatFailCount = 0; + } catch (RuntimeException e) { + // Workaround for problems seen on Intel 82855 cards in particular + // Make it look like the lockSurface() call didn't succeed + unlockSurface(); + if (e instanceof GLException) { + if (++setPixelFormatFailCount == MAX_SET_PIXEL_FORMAT_FAIL_COUNT) { + setPixelFormatFailCount = 0; + throw e; + } + return NativeWindow.LOCK_SURFACE_NOT_READY; + } else { + // Probably a user error in the GLCapabilitiesChooser or similar. + // Don't propagate non-GLExceptions out because calling code + // expects to catch only that exception type + throw new GLException(e); + } + } + } + return ret; + } + + + protected void choosePixelFormat(boolean onscreen) { + PIXELFORMATDESCRIPTOR pfd = null; + int pixelFormat = 0; + GLCapabilities chosenCaps = null; + GLCapabilities capabilities = getCapabilities(); + long hdc = getNativeWindow().getWindowHandle(); + if (onscreen) { + if ((pixelFormat = 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)); + } + pfd = newPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) { + // FIXME: should this just be a warning? Not really critical... + throw new GLException("Unable to describe pixel format " + pixelFormat + + " of window set by Java2D/OpenGL pipeline"); + } + setChosenGLCapabilities(pfd2GLCapabilities(pfd)); + pixelFormatChosen = true; + return; + } + + GLCapabilities[] availableCaps = null; + int numFormats = 0; + pfd = newPixelFormatDescriptor(); + // Produce a recommended pixel format selection for the GLCapabilitiesChooser. + // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available + WindowsWGLDrawable dummyDrawable = null; + GLContextImpl dummyContext = null; + WGLExt dummyWGLExt = null; + if (capabilities.getSampleBuffers()) { + dummyDrawable = new WindowsDummyWGLDrawable(getFactory()); + 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) { + try { + haveWGLChoosePixelFormatARB = dummyWGLExt.isExtensionAvailable("WGL_ARB_pixel_format"); + if (haveWGLChoosePixelFormatARB) { + haveWGLARBMultisample = dummyWGLExt.isExtensionAvailable("WGL_ARB_multisample"); + + int[] iattributes = new int [2 * MAX_ATTRIBS]; + int[] iresults = new int [2 * MAX_ATTRIBS]; + float[] fattributes = new float[1]; + + if (glCapabilities2iattributes(capabilities, + iattributes, + dummyWGLExt, + false, + null)) { + 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) + int niattribs = 0; + iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; + if (dummyWGLExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { + numFormats = iresults[0]; + + if (DEBUG) { + System.err.println("wglGetPixelFormatAttribivARB reported WGL_NUMBER_PIXEL_FORMATS_ARB = " + numFormats); + } + + // 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, niattribs, iresults, true); + } + gotAvailableCaps = true; + } else { + long 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); + } + } + + // NOTE: officially, should make a copy of all of these + // GLCapabilities to avoid mutation by the end user during the + // chooseCapabilities call, but for the time being, assume they + // won't be changed + + // 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]); + } + chosenCaps = 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)) { + long 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); + } + // Reuse the previously-constructed GLCapabilities because it + // turns out that using DescribePixelFormat on some pixel formats + // (which, for example, support full-scene antialiasing) for some + // reason return that they are not OpenGL-capable + if (chosenCaps != null) { + setChosenGLCapabilities(chosenCaps); + } else { + setChosenGLCapabilities(pfd2GLCapabilities(pfd)); + } + pixelFormatChosen = true; + } + + protected 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; + } + if (caps.getStereo()) { + pfdFlags |= WGL.PFD_STEREO; + } + 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; + } + + protected static PIXELFORMATDESCRIPTOR newPixelFormatDescriptor() { + PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); + pfd.nSize((short) pfd.size()); + pfd.nVersion((short) 1); + return pfd; + } + + protected 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; + } + + protected static boolean glCapabilities2iattributes(GLCapabilities capabilities, + int[] iattributes, + WGLExt wglExt, + boolean pbuffer, + int[] floatMode) throws GLException { + if (!wglExt.isExtensionAvailable("WGL_ARB_pixel_format")) { + return false; + } + + int niattribs = 0; + + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + if (pbuffer) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + + 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 (wglExt.isExtensionAvailable("WGL_ARB_multisample")) { + 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(); + } + } + + boolean rtt = capabilities.getPbufferRenderToTexture(); + boolean rect = capabilities.getPbufferRenderToTextureRectangle(); + boolean useFloat = capabilities.getPbufferFloatingPointBuffers(); + boolean ati = false; + if (pbuffer) { + // Check some invariants and set up some state + if (rect && !rtt) { + 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[0] = GLPbuffer.NV_FLOAT; + } else { + ati = true; + floatMode[0] = GLPbuffer.ATI_FLOAT; + } + if (DEBUG) { + System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension"); + } + } + + // See whether we need to change the pixel type to support ATI's + // floating-point pbuffers + 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; + } + } + + 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; + } + } + } else { + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; + } + + return true; + } + + protected static GLCapabilities iattributes2GLCapabilities(int[] iattribs, + int niattribs, + int[] iresults, + boolean requireRenderToWindow) { + GLCapabilities res = new GLCapabilities(); + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + if (requireRenderToWindow && iresults[i] != GL.GL_TRUE) + return null; + break; + + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + 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: + // Fail softly with unknown results here + if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB || + iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ATI) { + res.setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_FLOAT_COMPONENTS_NV: + if (iresults[i] != 0) { + res.setPbufferFloatingPointBuffers(true); + } + 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] != 0); + 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/wgl/WindowsWGLDrawableFactory.java b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java new file mode 100644 index 000000000..fd4e5620c --- /dev/null +++ b/src/classes/com/sun/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -0,0 +1,276 @@ +/* + * 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.wgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import com.sun.opengl.impl.*; +import javax.media.opengl.util.BufferUtil; + +public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { + private static final boolean DEBUG = Debug.debug("WindowsWGLDrawableFactory"); + 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.loadCore(); + } + + public WindowsWGLDrawableFactory() { + super(); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + AbstractGraphicsDevice device) { + return null; + } + + public GLDrawable createGLDrawable(NativeWindow target, + GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if (capabilities == null) { + capabilities = new GLCapabilities(); + } + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + return new WindowsOnscreenWGLDrawable(this, target, capabilities, chooser); + } + + public GLDrawableImpl createOffscreenDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser) { + return new WindowsOffscreenWGLDrawable(this, capabilities, chooser); + } + + private boolean pbufferSupportInitialized = false; + private boolean canCreateGLPbuffer = false; + public boolean canCreateGLPbuffer() { + if (!pbufferSupportInitialized) { + final GLDrawableFactory factory = this; + Runnable r = new Runnable() { + public void run() { + WindowsDummyWGLDrawable dummyDrawable = new WindowsDummyWGLDrawable(factory); + 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); + } + if (DEBUG) { + System.err.println("WindowsWGLDrawableFactory.canCreateGLPbuffer() = " + canCreateGLPbuffer); + } + return canCreateGLPbuffer; + } + + public GLPbuffer createGLPbuffer(final GLCapabilities capabilities, + final GLCapabilitiesChooser chooser, + 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(); + final GLDrawableFactory factory = this; + Runnable r = new Runnable() { + public void run() { + WindowsDummyWGLDrawable dummyDrawable = new WindowsDummyWGLDrawable(factory); + WindowsWGLContext dummyContext = (WindowsWGLContext) dummyDrawable.createContext(null); + GLContext lastContext = GLContext.getCurrent(); + if (lastContext != null) { + lastContext.release(); + } + dummyContext.makeCurrent(); + WGLExt dummyWGLExt = dummyContext.getWGLExt(); + try { + WindowsPbufferWGLDrawable pbufferDrawable = new WindowsPbufferWGLDrawable(factory, 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 WindowsExternalWGLContext(); + } + + public boolean canCreateExternalGLDrawable() { + return true; + } + + public GLDrawable createExternalGLDrawable() { + return WindowsExternalWGLDrawable.create(this); + } + + public void loadGLULibrary() { + if (hglu32 == 0) { + hglu32 = WGL.LoadLibraryA("GLU32"); + if (hglu32 == 0) { + throw new GLException("Error loading GLU32.DLL"); + } + } + } + + 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) { + res = WGL.GetProcAddress(hglu32, glFuncName); + } + } + return res; + } + + static String wglGetLastError() { + long err = WGL.GetLastError(); + String detail = null; + switch ((int) 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 boolean canCreateContextOnJava2DSurface() { + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("Unimplemented on this platform"); + } + + //------------------------------------------------------ + // Gamma-related functionality + // + + private static final int GAMMA_RAMP_LENGTH = 256; + + protected int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected boolean setGammaRamp(float[] ramp) { + short[] rampData = new short[3 * GAMMA_RAMP_LENGTH]; + for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) { + short scaledValue = (short) (ramp[i] * 65535); + rampData[i] = scaledValue; + rampData[i + GAMMA_RAMP_LENGTH] = scaledValue; + rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue; + } + + long screenDC = WGL.GetDC(0); + boolean res = WGL.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData)); + WGL.ReleaseDC(0, screenDC); + return res; + } + + protected Buffer getGammaRamp() { + ShortBuffer rampData = ShortBuffer.allocate(3 * GAMMA_RAMP_LENGTH); + long screenDC = WGL.GetDC(0); + boolean res = WGL.GetDeviceGammaRamp(screenDC, rampData); + WGL.ReleaseDC(0, screenDC); + if (!res) { + return null; + } + return rampData; + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + // getGammaRamp failed earlier + return; + } + long screenDC = WGL.GetDC(0); + WGL.SetDeviceGammaRamp(screenDC, originalGammaRamp); + WGL.ReleaseDC(0, screenDC); + } +} |