diff options
author | Sven Gothel <[email protected]> | 2011-02-08 06:20:35 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-02-08 06:20:35 +0100 |
commit | 4cda4b70dbcd21cf57e1e253ddba32b88bcaec18 (patch) | |
tree | 6f16d211cb80ebf5dcc8cab6424c70079a38ea7f /src/jogl/classes/jogamp/opengl/windows/wgl | |
parent | eb7986963c87bc6f33e7f18bb90ddf898b7dd63a (diff) |
Move implementation private files from com.jogamp.<module>.impl. to jogamp.<module> (1/2) - rename task
- com.jogamp.opengl.impl -> jogamp.opengl
- com.jogamp.opengl.util.glsl.fixedfunc.impl -> jogamp.opengl.util.glsl.fixedfunc
- com.jogamp.nativewindow.impl -> jogamp.nativewindow
- com.jogamp.newt.impl -> jogamp.newt
This sorts implementation details from the top level, ie skipping the public 'com',
allowing a better seperation of public classes and implementation details
and also reduces strings.
This approach of public/private seperation is also used in the OpenJDK.
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/windows/wgl')
17 files changed, 3912 insertions, 0 deletions
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java new file mode 100644 index 000000000..b5be4bf8d --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java @@ -0,0 +1,243 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.util.Comparator; + +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +public class WGLGLCapabilities extends GLCapabilities { + PIXELFORMATDESCRIPTOR pfd; + int pfdID; + int arb_pixelformat; // -1 PFD, 0 NOP, 1 ARB + + /** Comparing pfd id only */ + public static class PfdIDComparator implements Comparator { + + public int compare(Object o1, Object o2) { + if ( ! ( o1 instanceof WGLGLCapabilities ) ) { + Class c = (null != o1) ? o1.getClass() : null ; + throw new ClassCastException("arg1 not a WGLGLCapabilities object: " + c); + } + if ( ! ( o2 instanceof WGLGLCapabilities ) ) { + Class c = (null != o2) ? o2.getClass() : null ; + throw new ClassCastException("arg2 not a WGLGLCapabilities object: " + c); + } + + final WGLGLCapabilities caps1 = (WGLGLCapabilities) o1; + final long id1 = caps1.getPFDID(); + + final WGLGLCapabilities caps2 = (WGLGLCapabilities) o2; + final long id2 = caps2.getPFDID(); + + if(id1 > id2) { + return 1; + } else if(id1 < id2) { + return -1; + } + return 0; + } + } + + public WGLGLCapabilities(PIXELFORMATDESCRIPTOR pfd, int pfdID, GLProfile glp) { + super(glp); + this.pfd = pfd; + this.pfdID = pfdID; + this.arb_pixelformat = 0; + } + + public boolean setValuesByGDI() { + arb_pixelformat = -1; + + setRedBits(pfd.getCRedBits()); + setGreenBits(pfd.getCGreenBits()); + setBlueBits(pfd.getCBlueBits()); + setAlphaBits(pfd.getCAlphaBits()); + setAccumRedBits(pfd.getCAccumRedBits()); + setAccumGreenBits(pfd.getCAccumGreenBits()); + setAccumBlueBits(pfd.getCAccumBlueBits()); + setAccumAlphaBits(pfd.getCAccumAlphaBits()); + setDepthBits(pfd.getCDepthBits()); + setStencilBits(pfd.getCStencilBits()); + setDoubleBuffered((pfd.getDwFlags() & GDI.PFD_DOUBLEBUFFER) != 0); + setStereo((pfd.getDwFlags() & GDI.PFD_STEREO) != 0); + setHardwareAccelerated((pfd.getDwFlags() & GDI.PFD_GENERIC_FORMAT) == 0 + || (pfd.getDwFlags() & GDI.PFD_GENERIC_ACCELERATED) != 0); + // n/a with non ARB/GDI method: + // multisample + // opaque + // pbuffer + + return true; + } + + public boolean setValuesByARB(final int[] iattribs, final int niattribs, final int[] iresults) { + arb_pixelformat = 1; + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + break; + + case WGLExt.WGL_ACCELERATION_ARB: + setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); + break; + + case WGLExt.WGL_SUPPORT_OPENGL_ARB: + if (iresults[i] != GL.GL_TRUE) { + return false; + } + break; + + case WGLExt.WGL_DEPTH_BITS_ARB: + setDepthBits(iresults[i]); + break; + + case WGLExt.WGL_STENCIL_BITS_ARB: + setStencilBits(iresults[i]); + break; + + case WGLExt.WGL_DOUBLE_BUFFER_ARB: + setDoubleBuffered(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_STEREO_ARB: + 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_ARB) { + setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_FLOAT_COMPONENTS_NV: + if (iresults[i] != 0) { + setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_RED_BITS_ARB: + setRedBits(iresults[i]); + break; + + case WGLExt.WGL_GREEN_BITS_ARB: + setGreenBits(iresults[i]); + break; + + case WGLExt.WGL_BLUE_BITS_ARB: + setBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ALPHA_BITS_ARB: + setAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_RED_BITS_ARB: + setAccumRedBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: + setAccumGreenBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: + setAccumBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: + setAccumAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_SAMPLE_BUFFERS_ARB: + setSampleBuffers(iresults[i] != 0); + break; + + case WGLExt.WGL_SAMPLES_ARB: + setNumSamples(iresults[i]); + break; + + default: + throw new GLException("Unknown pixel format attribute " + iattribs[i]); + } + } + return true; + } + + public Object cloneMutable() { + return clone(); + } + + public Object clone() { + try { + return super.clone(); + } catch (RuntimeException e) { + throw new GLException(e); + } + } + + final public PIXELFORMATDESCRIPTOR getPFD() { return pfd; } + final public int getPFDID() { return pfdID; } + + final public boolean isSetByARB() { return 0 < arb_pixelformat; } + final public boolean isSetByGDI() { return 0 > arb_pixelformat; } + final public boolean isSet() { return 0 != arb_pixelformat; } + + public StringBuffer toString(StringBuffer sink) { + if(null == sink) { + sink = new StringBuffer(); + } + sink.append(pfdID).append(" "); + switch (arb_pixelformat) { + case -1: + sink.append("gdi"); + break; + case 0: + sink.append("nop"); + break; + case 1: + sink.append("arb"); + break; + default: + throw new InternalError("invalid arb_pixelformat: " + arb_pixelformat); + } + sink.append(": "); + return super.toString(sink); + } +}
\ No newline at end of file diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java new file mode 100644 index 000000000..7b769d971 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; + +public class WindowsBitmapWGLContext extends WindowsWGLContext { + public WindowsBitmapWGLContext(WindowsBitmapWGLDrawable 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/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java new file mode 100644 index 000000000..c61a8d0e4 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceChangeable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; + +import com.jogamp.nativewindow.impl.windows.BITMAPINFO; +import com.jogamp.nativewindow.impl.windows.BITMAPINFOHEADER; +import com.jogamp.nativewindow.impl.windows.GDI; +import javax.media.opengl.GLCapabilitiesImmutable; + +public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { + private long origbitmap; + private long hbitmap; + + protected WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface target) { + super(factory, target, true); + create(); + } + + protected void setRealizedImpl() { + if(realized) { + create(); + } else { + destroyImpl(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsBitmapWGLContext(this, shareWith); + } + + private void create() { + int werr; + NativeSurface ns = getNativeSurface(); + if(DEBUG) { + System.err.println("WindowsBitmapWGLDrawable (1): "+ns); + } + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); + int width = getWidth(); + int height = getHeight(); + + // + // 1. Create DIB Section + // + BITMAPINFO info = BITMAPINFO.create(); + BITMAPINFOHEADER header = info.getBmiHeader(); + int bitsPerPixel = (capabilities.getRedBits() + + capabilities.getGreenBits() + + capabilities.getBlueBits() + + capabilities.getAlphaBits()); + header.setBiSize(header.size()); + header.setBiWidth(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.setBiHeight(-1 * height); + header.setBiPlanes((short) 1); + header.setBiBitCount((short) bitsPerPixel); + header.setBiXPelsPerMeter(0); + header.setBiYPelsPerMeter(0); + header.setBiClrUsed(0); + header.setBiClrImportant(0); + header.setBiCompression(GDI.BI_RGB); + int byteNum = width * height * ( bitsPerPixel >> 3 ) ; + header.setBiSizeImage(byteNum); + + PointerBuffer pb = PointerBuffer.allocateDirect(1); + hbitmap = GDI.CreateDIBSection(0, info, GDI.DIB_RGB_COLORS, pb, 0, 0); + werr = GDI.GetLastError(); + if(DEBUG) { + long p = ( pb.capacity() > 0 ) ? pb.get(0) : 0; + System.err.println("WindowsBitmapWGLDrawable: pb sz/ptr "+pb.capacity() + ", "+toHexString(p)); + System.err.println("WindowsBitmapWGLDrawable: " + width+"x"+height + + ", bpp " + bitsPerPixel + + ", bytes " + byteNum + + ", header sz " + header.size() + + ", DIB ptr num " + pb.capacity()+ + ", "+capabilities+ + ", werr "+werr); + } + if (hbitmap == 0) { + throw new GLException("Error creating offscreen bitmap of " + ns + ", werr " + werr); + } + + // + // 2. Create memory DC (device context) , and associate it with the DIB. + // + long hdc = GDI.CreateCompatibleDC(0); + werr = GDI.GetLastError(); + if (hdc == 0) { + GDI.DeleteObject(hbitmap); + hbitmap = 0; + throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr); + } + ((SurfaceChangeable)ns).setSurfaceHandle(hdc); + if(DEBUG) { + System.err.println("WindowsBitmapWGLDrawable (2): "+ns); + } + + if ((origbitmap = GDI.SelectObject(hdc, hbitmap)) == 0) { + GDI.DeleteObject(hbitmap); + hbitmap = 0; + GDI.DeleteDC(hdc); + hdc = 0; + throw new GLException("Error selecting bitmap into new device context"); + } + + config.updateGraphicsConfiguration(getFactory(), ns, null); + } + + protected void destroyImpl() { + NativeSurface ns = getNativeSurface(); + if (ns.getSurfaceHandle() != 0) { + // Must destroy bitmap and device context + GDI.SelectObject(ns.getSurfaceHandle(), origbitmap); + GDI.DeleteObject(hbitmap); + GDI.DeleteDC(ns.getSurfaceHandle()); + origbitmap = 0; + hbitmap = 0; + ((SurfaceChangeable)ns).setSurfaceHandle(0); + } + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java new file mode 100644 index 000000000..a307e295d --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLProfile; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import com.jogamp.nativewindow.impl.ProxySurface; +import com.jogamp.nativewindow.impl.windows.GDI; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; + +public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { + private static final int f_dim = 64; + private long hwnd, hdc; + + protected WindowsDummyWGLDrawable(GLDrawableFactory factory, GLCapabilitiesImmutable caps, AbstractGraphicsScreen absScreen) { + super(factory, new ProxySurface(WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen)), true); + hwnd = GDI.CreateDummyWindow(0, 0, f_dim, f_dim); + if(0 == hwnd) { + throw new GLException("Error hwnd 0, werr: "+GDI.GetLastError()); + } + // manual debug only - GDI.ShowWindow(hwnd, GDI.SW_SHOW); + ProxySurface ns = (ProxySurface) getNativeSurface(); + ns.setSize(f_dim, f_dim); + + if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { + throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)"); + } + try { + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(factory, ns, null); + if (DEBUG) { + System.err.println("!!! WindowsDummyWGLDrawable: "+config); + } + } catch (Throwable t) { + destroyImpl(); + throw new GLException(t); + } finally { + unlockSurface(); + } + } + + public static WindowsDummyWGLDrawable create(GLDrawableFactory factory, GLProfile glp, AbstractGraphicsScreen absScreen) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setDepthBits(16); + caps.setDoubleBuffered(true); + caps.setOnscreen (true); + return new WindowsDummyWGLDrawable(factory, caps, absScreen); + } + + public int lockSurface() throws GLException { + int res = NativeSurface.LOCK_SURFACE_NOT_READY; + ProxySurface ns = (ProxySurface) getNativeSurface(); + AbstractGraphicsDevice adevice = ns.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + adevice.lock(); + try { + res = ns.lockSurface(); + if(NativeSurface.LOCK_SUCCESS == res) { + if(0 == hdc) { + hdc = GDI.GetDC(hwnd); + ns.setSurfaceHandle(hdc); + if(0 == hdc) { + res = NativeSurface.LOCK_SURFACE_NOT_READY; + ns.unlockSurface(); + throw new GLException("Error hdc 0, werr: "+GDI.GetLastError()); + // finally will unlock adevice + } + } + } else { + Throwable t = new Throwable("Error lock failed - res "+res+", hwnd "+toHexString(hwnd)+", hdc "+toHexString(hdc)); + t.printStackTrace(); + } + } finally { + if( NativeSurface.LOCK_SURFACE_NOT_READY == res ) { + adevice.unlock(); + } + } + return res; + } + + public void unlockSurface() { + ProxySurface ns = (ProxySurface) getNativeSurface(); + ns.validateSurfaceLocked(); + AbstractGraphicsDevice adevice = ns.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice(); + + try { + if ( 0 != hdc && 0 != hwnd && ns.getSurfaceRecursionCount() == 0) { + GDI.ReleaseDC(hwnd, hdc); + hdc=0; + ns.setSurfaceHandle(hdc); + } + surface.unlockSurface(); + } finally { + adevice.unlock(); + } + } + + public void setSize(int width, int height) { + } + + public int getWidth() { + return 1; + } + + public int getHeight() { + return 1; + } + + public GLContext createContext(GLContext shareWith) { + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + return new WindowsWGLContext(this, shareWith); + } + + protected void destroyImpl() { + if (hdc != 0) { + GDI.ReleaseDC(hwnd, hdc); + hdc = 0; + ProxySurface ns = (ProxySurface) getNativeSurface(); + ns.setSurfaceHandle(hdc); + } + if (hwnd != 0) { + GDI.ShowWindow(hwnd, GDI.SW_HIDE); + GDI.DestroyDummyWindow(hwnd); + hwnd = 0; + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java new file mode 100644 index 000000000..cfe0a7899 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.impl.ProxySurface; +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.opengl.impl.GLContextShareSet; + + +public class WindowsExternalWGLContext extends WindowsWGLContext { + private boolean firstMakeCurrent = true; + private GLContext lastContext; + + private WindowsExternalWGLContext(Drawable drawable, long ctx, WindowsWGLGraphicsConfiguration cfg) { + super(drawable, null); + this.contextHandle = ctx; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(ctx) + " for " + this); + } + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static WindowsExternalWGLContext create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current, werr " + GDI.GetLastError()); + } + long ctx = WGL.wglGetCurrentContext(); + if (ctx == 0) { + throw new GLException("Error: attempted to make an external GLContext without a context current, werr " + GDI.GetLastError()); + } + int pfdID = GDI.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError()); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromCurrent(factory, hdc, pfdID, glp, aScreen, true, true); + return new WindowsExternalWGLContext(new Drawable(factory, new ProxySurface(cfg, hdc)), ctx, cfg); + } + + 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 void makeCurrentImpl(boolean newCreated) throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + } + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends WindowsWGLDrawable { + Drawable(GLDrawableFactory factory, NativeSurface comp) { + super(factory, comp, true); + } + + public GLContext createContext(GLContext shareWith) { + 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 setSize(int width, int height) { + throw new GLException("Should not call this"); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java new file mode 100644 index 000000000..2851473d5 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.impl.ProxySurface; +import com.jogamp.nativewindow.impl.windows.GDI; + +public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { + + private WindowsExternalWGLDrawable(GLDrawableFactory factory, NativeSurface component) { + super(factory, component, true); + } + + protected static WindowsExternalWGLDrawable create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current, werr " + GDI.GetLastError()); + } + int pfdID = GDI.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError()); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromCurrent(factory, hdc, pfdID, glp, aScreen, true, true); + return new WindowsExternalWGLDrawable(factory, new ProxySurface(cfg, hdc)); + } + + + 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"); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java new file mode 100644 index 000000000..475faeecc --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java @@ -0,0 +1,53 @@ +/* + * 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.jogamp.opengl.impl.windows.wgl; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLContext extends WindowsWGLContext { + public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java new file mode 100644 index 000000000..b0d62a4e1 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable { + protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeSurface component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOnscreenWGLContext(this, shareWith); + } + +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java new file mode 100644 index 000000000..db86b3232 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java @@ -0,0 +1,147 @@ +/* + * 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsPbufferWGLContext extends WindowsWGLContext { + // State for render-to-texture and render-to-texture-rectangle support + 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); + } + + 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(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), 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(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError()); + } + } + } + + protected void makeCurrentImpl(boolean newCreated) throws GLException { + super.makeCurrentImpl(newCreated); + if (newCreated) { + GLCapabilitiesImmutable capabilities = drawable.getChosenGLCapabilities(); + + // Initialize render-to-texture support if requested + GL gl = getGL(); + rtt = capabilities.getPbufferRenderToTexture(); + rect = gl.isGL2GL3() && 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_ARB; + } 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); + } + } + } + } + + public int getFloatingPointMode() { + return ((WindowsPbufferWGLDrawable)drawable).getFloatingPointMode(); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java new file mode 100644 index 000000000..a8d37796e --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceChangeable; +import javax.media.opengl.GL; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.impl.windows.GDI; +import javax.media.opengl.GLCapabilitiesImmutable; + +public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { + 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, NativeSurface target, + WindowsWGLDrawable dummyDrawable, + WindowsWGLContext sharedCtx) { + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + createPbuffer(dummyDrawable.getNativeSurface().getSurfaceHandle(), sharedCtx); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + throw new GLException("Recreation via setRealized not supported."); + } else { + destroyImpl(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsPbufferWGLContext(this, shareWith); + } + + protected void destroyImpl() { + NativeSurface ns = getNativeSurface(); + if(0!=buffer) { + WGLExt wglExt = cachedWGLExt; + if (ns.getSurfaceHandle() != 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) + if (wglExt.wglReleasePbufferDCARB(buffer, ns.getSurfaceHandle()) == 0) { + throw new GLException("Error releasing pbuffer device context: error code " + GDI.GetLastError()); + } + ((SurfaceChangeable)ns).setSurfaceHandle(0); + } + if (!wglExt.wglDestroyPbufferARB(buffer)) { + throw new GLException("Error destroying pbuffer: error code " + GDI.GetLastError()); + } + buffer = 0; + } + } + + public long getPbufferHandle() { + // The actual to-be-used handle for makeCurrent etc, + // is the derived DC, set in the NativeSurface surfaceHandle + // returned by getHandle(). + return buffer; + } + + public int getFloatingPointMode() { + return floatMode; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + + private void createPbuffer(long parentHdc, WindowsWGLContext sharedCtx) { + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + int[] floatModeTmp = new int[1]; + int niattribs = 0; + int width, height; + WGLExt wglExt = sharedCtx.getWGLExt(); + + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + GLProfile glProfile = chosenCaps.getGLProfile(); + + if (DEBUG) { + System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc)); + System.out.println("Pbuffer chosenCaps: " + chosenCaps); + } + + if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps, + iattributes, sharedCtx, -1, floatModeTmp)){ + throw new GLException("Pbuffer-related extensions not supported"); + } + + floatMode = floatModeTmp[0]; + boolean rtt = chosenCaps.getPbufferRenderToTexture(); + boolean rect = chosenCaps.getPbufferRenderToTextureRectangle(); + boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers(); + boolean ati = false; + + if (useFloat) { + ati = (floatMode == GLPbuffer.ATI_FLOAT); + } + + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int nformats; + int[] nformatsTmp = new int[1]; + if (!wglExt.wglChoosePixelFormatARB(parentHdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + nformatsTmp, 0)) { + throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); + } + nformats = nformatsTmp[0]; + if (nformats <= 0) { + throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); + } + + if (DEBUG) { + System.err.println("" + nformats + " suitable pixel formats found"); + for (int i = 0; i < nformats; i++) { + WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedCtx, parentHdc, pformats[i], glProfile, false, true); + System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps); + } + } + + int pfdid = 0; + long tmpBuffer = 0; + { + int whichFormat; + // 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 (0 == tmpBuffer) { + throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + + " pixel formats, last error was: " + wglGetLastError()); + } + pfdid = pformats[whichFormat]; + } + + // Get the device context. + long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer); + if (tmpHdc == 0) { + throw new GLException("pbuffer creation error: wglGetPbufferDC() failed"); + } + + NativeSurface ns = getNativeSurface(); + // Set up instance variables + buffer = tmpBuffer; + ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc); + cachedWGLExt = wglExt; + + // Re-query chosen pixel format + { + WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedCtx, parentHdc, pfdid, glProfile, false, true); + if(null == newCaps) { + throw new GLException("pbuffer creation error: unable to re-query chosen PFD ID: " + pfdid + ", hdc " + this.toHexString(tmpHdc)); + } + if(newCaps.isOnscreen() || !newCaps.isPBuffer()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps); + } + config.setCapsPFD(newCaps); + } + + // 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]; + ((SurfaceChangeable)ns).setSize(width, height); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java new file mode 100644 index 000000000..7d38f8ee8 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLCapabilitiesImmutable; + +import com.jogamp.gluegen.runtime.ProcAddressTable; +import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.opengl.impl.GLContextImpl; +import com.jogamp.opengl.impl.GLContextShareSet; +import com.jogamp.opengl.impl.GLDrawableImpl; + +public class WindowsWGLContext extends GLContextImpl { + static final Map/*<String, String>*/ functionNameMap; + static final Map/*<String, String>*/ extensionNameMap; + private boolean wglGetExtensionsStringEXTInitialized; + private boolean wglGetExtensionsStringEXTAvailable; + private boolean wglGLReadDrawableAvailableSet; + private boolean wglGLReadDrawableAvailable; + 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 + WindowsWGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + protected void resetState() { + wglGetExtensionsStringEXTInitialized=false; + wglGetExtensionsStringEXTAvailable=false; + wglGLReadDrawableAvailableSet=false; + wglGLReadDrawableAvailable=false; + // no inner state _wglExt=null; + wglExtProcAddressTable=null; + } + + public Object getPlatformGLExtensions() { + return getWGLExt(); + } + + /* package private */ final WGLExt getWGLExt() { + if( null == getWGLExtProcAddressTable()) { + throw new InternalError("Null WGLExtProcAddressTable"); + } + if (wglExt == null) { + wglExt = new WGLExtImpl(this); + } + return wglExt; + } + + public final boolean isGLReadDrawableAvailable() { + if(!wglGLReadDrawableAvailableSet && null != getWGLExtProcAddressTable()) { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + switch( factory.isReadDrawableAvailable(device) ) { + case 1: + wglGLReadDrawableAvailable = true; + wglGLReadDrawableAvailableSet=true; + break; + case 0: + wglGLReadDrawableAvailable = false; + wglGLReadDrawableAvailableSet=true; + break; + } + } + return wglGLReadDrawableAvailable; + } + + private final boolean wglMakeContextCurrent(long hDrawDC, long hReadDC, long ctx) { + boolean ok = false; + if(wglGLReadDrawableAvailable) { + // needs initilized WGL ProcAddress table + ok = getWGLExt().wglMakeContextCurrent(hDrawDC, hReadDC, ctx); + } else if ( hDrawDC == hReadDC ) { + ok = WGL.wglMakeCurrent(hDrawDC, ctx); + } else { + // should not happen due to 'isGLReadDrawableAvailable()' query in GLContextImpl + throw new InternalError("Given readDrawable but no driver support"); + } + int werr = ( !ok ) ? GDI.GetLastError() : GDI.ERROR_SUCCESS; + if(DEBUG && !ok) { + Throwable t = new Throwable ("Info: wglMakeContextCurrent draw "+ + this.toHexString(hDrawDC) + ", read " + this.toHexString(hReadDC) + + ", ctx " + this.toHexString(ctx) + ", werr " + werr); + t.printStackTrace(); + } + if(!ok && 0==hDrawDC && 0==hReadDC) { + // Some GPU's falsely fails with a zero error code (success), + // in case this is a release context request we tolerate this + return werr == GDI.ERROR_SUCCESS ; + } + return ok; + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getWGLExtProcAddressTable(); + } + + public final WGLExtProcAddressTable getWGLExtProcAddressTable() { + return wglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return functionNameMap; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } + + protected void destroyContextARBImpl(long context) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(context); + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + if( null == getWGLExtProcAddressTable()) { + updateGLXProcAddressTable(); + } + WGLExt _wglExt = getWGLExt(); + if(DEBUG) { + System.err.println(getThreadName()+" - WindowWGLContext.createContextARBImpl: "+getGLVersion(major, minor, ctp, "@creation") + + ", handle "+toHexString(drawable.getHandle()) + ", share "+toHexString(share)+", direct "+direct+ + ", wglCreateContextAttribsARB: "+toHexString(wglExtProcAddressTable._addressof_wglCreateContextAttribsARB)); + Thread.dumpStack(); + } + + boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + long ctx=0; + + final int idx_flags = 4; + final int idx_profile = 6; + + /* WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, */ + + int attribs[] = { + /* 0 */ WGLExt.WGL_CONTEXT_MAJOR_VERSION_ARB, major, + /* 2 */ WGLExt.WGL_CONTEXT_MINOR_VERSION_ARB, minor, + /* 4 */ WGLExt.WGL_CONTEXT_FLAGS_ARB, 0, + /* 6 */ 0, 0, + /* 8 */ 0 + }; + + if ( major > 3 || major == 3 && minor >= 2 ) { + // FIXME: Verify with a None drawable binding (default framebuffer) + attribs[idx_profile+0] = WGLExt.WGL_CONTEXT_PROFILE_MASK_ARB; + if( ctBwdCompat ) { + attribs[idx_profile+1] = WGLExt.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } else { + attribs[idx_profile+1] = WGLExt.WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + } + } + + if ( major >= 3 ) { + if( !ctBwdCompat && ctFwdCompat ) { + attribs[idx_flags+1] |= WGLExt.WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if( ctDebug) { + attribs[idx_flags+1] |= WGLExt.WGL_CONTEXT_DEBUG_BIT_ARB; + } + } + + try { + ctx = _wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribs, 0); + } catch (RuntimeException re) { + if(DEBUG) { + Throwable t = new Throwable("Info: WindowWGLContext.createContextARBImpl wglCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re); + t.printStackTrace(); + } + } + + if(0!=ctx) { + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), ctx)) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContextARB couldn't make current "+getGLVersion(major, minor, ctp, "@creation")); + } + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(ctx); + ctx = 0; + } else { + if (DEBUG) { + System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct); + } + // the following is issued by the caller 'GLContextImpl.createContextARB()' + // setGLFunctionAvailability(true, major, minor, ctp); + } + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextARBImpl: NO "+getGLVersion(major, minor, ctp, "@creation")); + } + return ctx; + } + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link #makeCurrentImpl()}. + */ + protected boolean createImpl() { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); + GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities(); + + isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable + + // Windows can set up sharing of display lists after creation time + WindowsWGLContext other = (WindowsWGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getHandle(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + + int minor[] = new int[1]; + int major[] = new int[1]; + int ctp[] = new int[1]; + boolean createContextARBTried = false; + + // utilize the shared context's GLXExt in case it was using the ARB method and it already exists + if( null!=sharedContext && sharedContext.isCreatedWithARBMethod() ) { + contextHandle = createContextARB(share, true, major, minor, ctp); + createContextARBTried = true; + if (DEBUG && 0!=contextHandle) { + System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+share); + } + } + + long temp_ctx = 0; + if(0==contextHandle) { + // To use WGL_ARB_create_context, we have to make a temp context current, + // so we are able to use GetProcAddress + temp_ctx = WGL.wglCreateContext(drawable.getHandle()); + if (temp_ctx == 0) { + throw new GLException("Unable to create temp OpenGL context for device context " + toHexString(drawable.getHandle())); + } + if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) { + throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + boolean isCreateContextAttribsARBAvailable = isFunctionAvailable("wglCreateContextAttribsARB"); + WGL.wglMakeCurrent(0, 0); // release temp context + + if( !createContextARBTried) { + if(isCreateContextAttribsARBAvailable && + isExtensionAvailable("WGL_ARB_create_context") ) { + // initial ARB context creation + contextHandle = createContextARB(share, true, major, minor, ctp); + createContextARBTried=true; + if (DEBUG) { + if(0!=contextHandle) { + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + } else { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share); + } + } + } else if (DEBUG) { + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share); + } + } + } + + if(0!=contextHandle) { + share = 0; // mark as shared thx to the ARB create method + if(0!=temp_ctx) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_ctx); + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); + } + } + } else { + if(glCaps.getGLProfile().isGL3()) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_ctx); + throw new GLException("WindowsWGLContext.createContext failed, but context > GL2 requested "+getGLVersion(major[0], minor[0], ctp[0], "@creation")+", "); + } + if(DEBUG) { + System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion(major[0], minor[0], ctp[0], "@creation")); + } + + // continue with temp context for GL < 3.0 + contextHandle = temp_ctx; + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(contextHandle); + throw new GLException("Error making old context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); + } + if (DEBUG) { + System.err.println(getThreadName() + ": createImpl: OK (old) share "+share); + } + } + + if(0!=share) { + if (!WGL.wglShareLists(share, contextHandle)) { + throw new GLException("wglShareLists(" + toHexString(share) + + ", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError()); + } + } + return true; + } + + protected void makeCurrentImpl(boolean newCreated) throws GLException { + if (WGL.wglGetCurrentContext() != contextHandle) { + if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { + throw new GLException("Error making context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError() + ", " + this); + } else { + if (DEBUG && newCreated) { + System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getHandle()) + + ", contextHandle " + toHexString(contextHandle) + ") succeeded"); + } + } + } + } + + protected void releaseImpl() throws GLException { + if (!wglMakeContextCurrent(0, 0, 0)) { + throw new GLException("Error freeing OpenGL context, werr: " + GDI.GetLastError()); + } + } + + protected void destroyImpl() throws GLException { + WGL.wglMakeCurrent(0, 0); + if (!WGL.wglDeleteContext(contextHandle)) { + throw new GLException("Unable to delete OpenGL context"); + } + } + + protected void copyImpl(GLContext source, int mask) throws GLException { + if (!WGL.wglCopyContext(source.getHandle(), getHandle(), mask)) { + throw new GLException("wglCopyContext failed"); + } + } + + protected final void updateGLXProcAddressTable() { + AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); + String key = adevice.getUniqueID(); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing WGL extension address table: "+key); + } + wglGetExtensionsStringEXTInitialized=false; + wglGetExtensionsStringEXTAvailable=false; + wglGLReadDrawableAvailableSet=false; + wglGLReadDrawableAvailable=false; + + WGLExtProcAddressTable table = null; + synchronized(mappedContextTypeObjectLock) { + table = (WGLExtProcAddressTable) mappedGLXProcAddress.get( key ); + } + if(null != table) { + wglExtProcAddressTable = table; + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable reusing key("+key+") -> "+table.hashCode()); + } + } else { + if (wglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by OpenGL context type bits so we can + // share them among contexts classes (GL4, GL4bc, GL3, GL3bc, ..) + wglExtProcAddressTable = new WGLExtProcAddressTable(new GLProcAddressResolver()); + } + resetProcAddressTable(wglExtProcAddressTable); + synchronized(mappedContextTypeObjectLock) { + mappedGLXProcAddress.put(key, getWGLExtProcAddressTable()); + if(DEBUG) { + System.err.println(getThreadName() + ": !!! GLContext WGL ProcAddressTable mapping key("+key+") -> "+getWGLExtProcAddressTable().hashCode()); + } + } + } + } + + public String getPlatformExtensionsString() { + if (!wglGetExtensionsStringEXTInitialized) { + wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0); + wglGetExtensionsStringEXTInitialized = true; + } + if (wglGetExtensionsStringEXTAvailable) { + return getWGLExt().wglGetExtensionsStringEXT(); + } else { + return ""; + } + } + + protected void setSwapIntervalImpl(int interval) { + WGLExt wglExt = getWGLExt(); + if (wglExt.isExtensionAvailable("WGL_EXT_swap_control")) { + if ( wglExt.wglSwapIntervalEXT(interval) ) { + currentSwapInterval = 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"); + } + +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java new file mode 100644 index 000000000..83b52fbcb --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import java.security.AccessController; +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; + +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.GLDrawableImpl; +import com.jogamp.opengl.impl.GLDynamicLookupHelper; + + +public abstract class WindowsWGLDrawable extends GLDrawableImpl { + private static final boolean PROFILING = Debug.isPropertyDefined("jogl.debug.GLDrawable.profiling", true, AccessController.getContext()); + private static final int PROFILING_TICKS = 200; + private int profilingSwapBuffersTicks; + private long profilingSwapBuffersTime; + + public WindowsWGLDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) { + super(factory, comp, realized); + } + + protected void setRealizedImpl() { + if(!realized) { + return; // nothing todo .. + } + + NativeSurface ns = getNativeSurface(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(getFactory(), ns, null); + if (DEBUG) { + System.err.println("!!! WindowsWGLDrawable.setRealized(true): "+config); + } + } + + protected void swapBuffersImpl() { + long startTime = 0; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + + if (!GDI.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { + 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; + } + } + } + + public GLDynamicLookupHelper getGLDynamicLookupHelper() { + return getFactoryImpl().getGLDynamicLookupHelper(0); + } + + static String getThreadName() { + return Thread.currentThread().getName(); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java new file mode 100644 index 000000000..f44c3c70b --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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.jogamp.opengl.impl.windows.wgl; + +import java.nio.Buffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.windows.WindowsGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.nio.PointerBuffer; +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.nativewindow.impl.ProxySurface; +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.RegisteredClassFactory; +import com.jogamp.opengl.impl.DesktopGLDynamicLookupHelper; +import com.jogamp.opengl.impl.GLContextImpl; +import com.jogamp.opengl.impl.GLDrawableFactoryImpl; +import com.jogamp.opengl.impl.GLDrawableImpl; +import com.jogamp.opengl.impl.GLDynamicLookupHelper; +import com.jogamp.opengl.impl.SharedResourceRunner; + +public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { + private static final DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper; + + static { + DesktopGLDynamicLookupHelper tmp = null; + try { + tmp = new DesktopGLDynamicLookupHelper(new WindowsWGLDynamicLibraryBundleInfo()); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + windowsWGLDynamicLookupHelper = tmp; + if(null!=windowsWGLDynamicLookupHelper) { + WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper); + } + } + + public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) { + return windowsWGLDynamicLookupHelper; + } + + public WindowsWGLDrawableFactory() { + super(); + + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new WindowsWGLGraphicsConfigurationFactory(); + if(GLProfile.isAWTAvailable()) { + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory", + null, getClass().getClassLoader()); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + + defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + + // Init shared resources off thread + // Will be released via ShutdownHook + sharedResourceImpl = new SharedResourceImplementation(); + sharedResourceRunner = new SharedResourceRunner(sharedResourceImpl); + sharedResourceThread = new Thread(sharedResourceRunner, Thread.currentThread().getName()+"-SharedResourceRunner"); + sharedResourceThread.setDaemon(true); // Allow JVM to exit, even if this one is running + sharedResourceThread.start(); + } + + WindowsGraphicsDevice defaultDevice; + SharedResourceImplementation sharedResourceImpl; + SharedResourceRunner sharedResourceRunner; + Thread sharedResourceThread; + HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap(); + + long processAffinityChanges = 0; + PointerBuffer procMask = PointerBuffer.allocateDirect(1); + PointerBuffer sysMask = PointerBuffer.allocateDirect(1); + + protected void enterThreadCriticalZone() { + synchronized (sysMask) { + if( 0 == processAffinityChanges) { + long pid = GDI.GetCurrentProcess(); + if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) { + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + Thread.dumpStack(); + } + processAffinityChanges = pid; + GDI.SetProcessAffinityMask(pid, 1); + } + } + } + } + + protected void leaveThreadCriticalZone() { + synchronized (sysMask) { + if( 0 != processAffinityChanges) { + long pid = GDI.GetCurrentProcess(); + if( pid != processAffinityChanges) { + throw new GLException("PID doesn't match: set PID 0x" + Long.toHexString(processAffinityChanges) + + " this PID 0x" + Long.toHexString(pid) ); + } + if(DEBUG) { + System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName()); + } + GDI.SetProcessAffinityMask(pid, sysMask.get(0)); + } + } + } + + static class SharedResource implements SharedResourceRunner.Resource { + private WindowsGraphicsDevice device; + private AbstractGraphicsScreen screen; + private WindowsDummyWGLDrawable drawable; + private WindowsWGLContext context; + private boolean canCreateGLPbuffer; + private boolean readDrawableAvailable; + + SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx, + boolean readBufferAvail, boolean canPbuffer) { + device = dev; + screen = scrn; + drawable = draw; + context = ctx; + canCreateGLPbuffer = canPbuffer; + readDrawableAvailable = readBufferAvail; + } + final public AbstractGraphicsDevice getDevice() { return device; } + final public AbstractGraphicsScreen getScreen() { return screen; } + final public GLDrawableImpl getDrawable() { return drawable; } + final public GLContextImpl getContext() { return context; } + + final boolean canCreateGLPbuffer() { return canCreateGLPbuffer; } + final boolean isReadDrawableAvailable() { return readDrawableAvailable; } + } + + class SharedResourceImplementation implements SharedResourceRunner.Implementation { + public void clear() { + synchronized(sharedMap) { + sharedMap.clear(); + } + } + public SharedResourceRunner.Resource mapPut(String connection, SharedResourceRunner.Resource resource) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.put(connection, resource); + } + } + public SharedResourceRunner.Resource mapGet(String connection) { + synchronized(sharedMap) { + return (SharedResourceRunner.Resource) sharedMap.get(connection); + } + } + public Collection/*<Resource>*/ mapValues() { + synchronized(sharedMap) { + return sharedMap.values(); + } + } + + public SharedResourceRunner.Resource createSharedResource(String connection) { + WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT); + sharedDevice.lock(); + try { + AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0); + if (null == absScreen) { + throw new GLException("Couldn't create shared screen for device: "+sharedDevice+", idx 0"); + } + GLProfile glp = GLProfile.getMinDesktop(sharedDevice); + if (null == glp) { + throw new GLException("Couldn't get default GLProfile for device: "+sharedDevice); + } + WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen); + if (null == sharedDrawable) { + throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp); + } + WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null); + if (null == sharedContext) { + throw new GLException("Couldn't create shared context for drawable: "+sharedDrawable); + } + sharedContext.setSynchronized(true); + boolean canCreateGLPbuffer; + boolean readDrawableAvailable; + sharedContext.makeCurrent(); + try { + canCreateGLPbuffer = sharedContext.getGL().isExtensionAvailable(GL_ARB_pbuffer); + readDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) && + sharedContext.isFunctionAvailable(wglMakeContextCurrent); + } finally { + sharedContext.release(); + } + if (DEBUG) { + System.err.println("!!! SharedDevice: " + sharedDevice); + System.err.println("!!! SharedScreen: " + absScreen); + System.err.println("!!! SharedContext: " + sharedContext); + System.err.println("!!! pbuffer avail: " + canCreateGLPbuffer); + System.err.println("!!! readDrawable: " + readDrawableAvailable); + } + return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext, readDrawableAvailable, canCreateGLPbuffer); + } catch (Throwable t) { + throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t); + } finally { + sharedDevice.unlock(); + } + } + + public void releaseSharedResource(SharedResourceRunner.Resource shared) { + SharedResource sr = (SharedResource) shared; + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! Device : " + sr.device); + System.err.println("!!! Screen : " + sr.screen); + System.err.println("!!! Drawable: " + sr.drawable); + System.err.println("!!! CTX : " + sr.context); + } + + if (null != sr.context) { + // may cause JVM SIGSEGV: sharedContext.destroy(); + sr.context = null; + } + + if (null != sr.drawable) { + sr.drawable.destroy(); + sr.drawable = null; + } + + if (null != sr.screen) { + sr.screen = null; + } + + if (null != sr.device) { + sr.device.close(); + sr.device = null; + } + } + } + + public final AbstractGraphicsDevice getDefaultDevice() { + return defaultDevice; + } + + public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) { + if(device instanceof WindowsGraphicsDevice) { + return true; + } + return false; + } + + final static String GL_ARB_pbuffer = "GL_ARB_pbuffer"; + final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read"; + final static String wglMakeContextCurrent = "wglMakeContextCurrent"; + + protected final GLContext getSharedContextImpl(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getShared(device); + if(null!=sr) { + return sr.getContext(); + } + return null; + } + + protected final boolean hasSharedContextImpl(AbstractGraphicsDevice device) { + return null != getSharedContextImpl(device); + } + + protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.getContext(); + } + return null; + } + + protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return sr.getDevice(); + } + return null; + } + + protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device); + if(null!=sr) { + return (WindowsWGLDrawable) sr.getDrawable(); + } + return null; + } + + SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) { + return (SharedResource) sharedResourceRunner.getOrCreateShared(device); + } + + protected final void shutdownInstance() { + sharedResourceRunner.releaseAndWait(); + RegisteredClassFactory.shutdownSharedClasses(); + } + + protected List/*GLCapabilitiesImmutable*/ getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) { + return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device); + } + + protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new WindowsOnscreenWGLDrawable(this, target); + } + + protected final GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + if(!chosenCaps.isPBuffer()) { + return new WindowsBitmapWGLDrawable(this, target); + } + + // PBuffer GLDrawable Creation + final AbstractGraphicsDevice device = config.getScreen().getDevice(); + + final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device); + if(null==sr) { + throw new IllegalArgumentException("No shared resource for "+device); + } + final List returnList = new ArrayList(); + Runnable r = new Runnable() { + public void run() { + GLContext lastContext = GLContext.getCurrent(); + if (lastContext != null) { + lastContext.release(); + } + sr.context.makeCurrent(); + try { + GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(WindowsWGLDrawableFactory.this, target, + sr.drawable, + sr.context); + returnList.add(pbufferDrawable); + } finally { + sr.context.release(); + if (lastContext != null) { + lastContext.makeCurrent(); + } + } + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLDrawableImpl) returnList.get(0); + } + + /** + * @return 1 if read drawable extension is available, 0 if not + * and -1 if undefined yet, ie no shared device exist at this point. + */ + public final int isReadDrawableAvailable(AbstractGraphicsDevice device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); + if(null!=sr) { + return sr.isReadDrawableAvailable() ? 1 : 0 ; + } + return -1; // undefined + } + + public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice); + if(null!=sr) { + return sr.canCreateGLPbuffer(); + } + return false; + } + + protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { + AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); + ProxySurface ns = new ProxySurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsChosen, capsRequested, chooser, screen) ); + ns.setSize(width, height); + return ns; + } + + protected final GLContext createExternalGLContextImpl() { + return WindowsExternalWGLContext.create(this, null); + } + + public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + return true; + } + + protected final GLDrawable createExternalGLDrawableImpl() { + return WindowsExternalWGLDrawable.create(this, null); + } + + static String wglGetLastError() { + long err = GDI.GetLastError(); + String detail = null; + switch ((int) err) { + case GDI.ERROR_SUCCESS: detail = "ERROR_SUCCESS"; break; + case GDI.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT"; break; + case GDI.ERROR_NO_SYSTEM_RESOURCES: detail = "ERROR_NO_SYSTEM_RESOURCES"; break; + case GDI.ERROR_INVALID_DATA: detail = "ERROR_INVALID_DATA"; break; + case GDI.ERROR_PROC_NOT_FOUND: detail = "ERROR_PROC_NOT_FOUND"; break; + case GDI.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE"; break; + default: detail = "(Unknown error code " + err + ")"; break; + } + return detail; + } + + public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return false; + } + + public final 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 final int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected final 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 = GDI.GetDC(0); + boolean res = GDI.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData)); + GDI.ReleaseDC(0, screenDC); + return res; + } + + protected final Buffer getGammaRamp() { + ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]); + long screenDC = GDI.GetDC(0); + boolean res = GDI.GetDeviceGammaRamp(screenDC, rampData); + GDI.ReleaseDC(0, screenDC); + if (!res) { + return null; + } + return rampData; + } + + protected final void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + // getGammaRamp failed earlier + return; + } + long screenDC = GDI.GetDC(0); + GDI.SetDeviceGammaRamp(screenDC, originalGammaRamp); + GDI.ReleaseDC(0, screenDC); + } +} diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java new file mode 100644 index 000000000..153680f8e --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java @@ -0,0 +1,58 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.opengl.impl.*; +import java.util.*; + +public class WindowsWGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBundleInfo { + protected WindowsWGLDynamicLibraryBundleInfo() { + super(); + } + + public List getToolLibNames() { + List/*<String>*/ libNamesList = new ArrayList(); + + libNamesList.add("OpenGL32"); + + return libNamesList; + } + + + public final List getToolGetProcAddressFuncNameList() { + List res = new ArrayList(); + res.add("wglGetProcAddress"); + return res; + } + + public final long toolDynamicLookupFunction(long toolGetProcAddressHandle, String funcName) { + return WGL.wglGetProcAddress(toolGetProcAddressHandle, funcName); + } +} + diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java new file mode 100644 index 000000000..f844bad76 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.util.ArrayList; +import java.util.List; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsConfiguration; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; +import com.jogamp.opengl.impl.GLContextImpl; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; + +public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + // Keep this under the same debug flag as the drawable factory for convenience + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format"; + final static String WGL_ARB_multisample = "WGL_ARB_multisample"; + + protected static final int MAX_PFORMATS = 256; + protected static final int MAX_ATTRIBS = 256; + + private GLCapabilitiesChooser chooser; + private boolean isChosen = false; + + WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser) { + super(screen, capsChosen, capsRequested); + this.chooser=chooser; + this.isChosen = false; + } + + WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, + WGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested) { + super(screen, capsChosen, capsRequested); + setCapsPFD(capsChosen); + this.chooser=null; + } + + + static WindowsWGLGraphicsConfiguration createFromCurrent(GLDrawableFactory _factory, long hdc, int pfdID, + GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen, boolean usePBuffer) + { + if(_factory==null) { + throw new GLException("Null factory"); + } + if(hdc==0) { + throw new GLException("Null HDC"); + } + if(pfdID<=0) { + throw new GLException("Invalid pixelformat id "+pfdID); + } + if(null==glp) { + glp = GLProfile.getDefault(screen.getDevice()); + } + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + AbstractGraphicsDevice device = screen.getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); + boolean hasARB = null != sharedContext && sharedContext.isExtensionAvailable(WGL_ARB_pixel_format) ; + + WGLGLCapabilities caps = null; + + if(hasARB) { + caps = wglARBPFID2GLCapabilities(sharedContext, hdc, pfdID, glp, onscreen, usePBuffer); + } else if(!usePBuffer) { + caps = PFD2GLCapabilities(glp, hdc, pfdID, onscreen); + } + if(null==caps) { + throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+", pfdID "+pfdID+", hasARB "+hasARB); + } + + return new WindowsWGLGraphicsConfiguration(screen, caps, caps); + } + + public Object clone() { + return super.clone(); + } + + /** + * Updates the graphics configuration in case it has been determined yet.<br> + * Uses the NativeSurface's HDC.<br> + * Ensures that a PIXELFORMAT is set. + * + * @param factory + * @param ns + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + * + * @see #isDetermined() + */ + public final void updateGraphicsConfiguration(GLDrawableFactory factory, NativeSurface ns, int[] pfIDs) { + WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, ns, pfIDs); + } + + /** + * Preselect the graphics configuration in case it has been determined yet.<br> + * Uses a shared device's HDC and the given pfdIDs to preselect the pfd. + * No PIXELFORMAT is set. + * + * @param factory + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + * + * @see #isDetermined() + */ + public final void preselectGraphicsConfiguration(GLDrawableFactory factory, int[] pfdIDs) { + AbstractGraphicsDevice device = getNativeGraphicsConfiguration().getScreen().getDevice(); + WindowsWGLGraphicsConfigurationFactory.preselectGraphicsConfiguration(chooser, factory, device, this, pfdIDs); + } + + final void setCapsPFD(WGLGLCapabilities caps) { + setChosenCapabilities(caps); + this.isChosen=true; + if (DEBUG) { + System.err.println("*** setCapsPFD: "+caps); + } + } + + public final boolean isDetermined() { return isChosen; } + public final PIXELFORMATDESCRIPTOR getPixelFormat() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).getPFD() : null; } + public final int getPixelFormatID() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).getPFDID() : 0; } + public final boolean isChoosenByARB() { return isChosen ? ((WGLGLCapabilities)capabilitiesChosen).isSetByARB() : false; } + + static int fillAttribsForGeneralWGLARBQuery(boolean haveWGLARBMultisample, int[] iattributes) { + int niattribs = 0; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_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; + } + // pbo float buffer + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; // ati + iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia + + return niattribs; + } + + static boolean wglARBPFIDValid(WindowsWGLContext sharedCtx, long hdc, int pfdID) { + int[] in = new int[1]; + int[] out = new int[1]; + in[0] = WGLExt.WGL_COLOR_BITS_ARB; + if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, 1, in, 0, out, 0)) { + // Some GPU's falsely fails with a zero error code (success) + return GDI.GetLastError() == GDI.ERROR_SUCCESS ; + } + return true; + } + + static int[] wglAllARBPFIDs(WindowsWGLContext sharedCtx, long hdc) { + int[] iattributes = new int[1]; + int[] iresults = new int[1]; + + WGLExt wglExt = sharedCtx.getWGLExt(); + iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { + if(DEBUG) { + System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + int numFormats = iresults[0]; + if(0 == numFormats) { + if(DEBUG) { + System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + int[] pfdIDs = new int[numFormats]; + for (int i = 0; i < numFormats; i++) { + pfdIDs[i] = 1 + i; + } + return pfdIDs; + } + + static WGLGLCapabilities wglARBPFID2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int pfdID, + GLProfile glp, boolean onscreen, boolean usePBuffer) { + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); + if (!haveWGLChoosePixelFormatARB) { + return null; + } + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); + + int[] iattributes = new int [2*MAX_ATTRIBS]; + int[] iresults = new int [2*MAX_ATTRIBS]; + + int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); + + if (!sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdID, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context"); + } + ArrayList bucket = new ArrayList(1); + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) { + return (WGLGLCapabilities) bucket.get(0); + } + return null; + } + + static int[] wglChoosePixelFormatARB(long hdc, WindowsWGLContext sharedContext, + GLCapabilitiesImmutable capabilities, + int[] iattributes, int accelerationMode, float[] fattributes) + { + + if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, sharedContext, accelerationMode, null)) + { + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB: GLCapabilities2AttribList failed: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + + int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int[] numFormatsTmp = new int[1]; + if ( !sharedContext.getWGLExt().wglChoosePixelFormatARB(hdc, iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformatsTmp, 0, numFormatsTmp, 0)) + { + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB: wglChoosePixelFormatARB failed: " + GDI.GetLastError()); + Thread.dumpStack(); + } + return null; + } + int numFormats = numFormatsTmp[0]; + int[] pformats = null; + if( 0 < numFormats ) { + pformats = new int[numFormats]; + System.arraycopy(pformatsTmp, 0, pformats, 0, numFormats); + } + if (DEBUG) { + System.err.println("wglChoosePixelFormatARB: NumFormats (wglChoosePixelFormatARB) accelMode 0x" + + Integer.toHexString(accelerationMode) + ": " + numFormats); + for (int i = 0; i < numFormats; i++) { + WGLGLCapabilities dbgCaps0 = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities( + sharedContext, hdc, pformats[i], + capabilities.getGLProfile(), capabilities.isOnscreen(), capabilities.isPBuffer()); + System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps0); + } + } + return pformats; + } + + static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2GLCapabilities(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp, boolean onscreen, boolean usePBuffer) { + final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); + return wglARBPFIDs2GLCapabilitiesImpl(sharedCtx, hdc, pfdIDs, glp, winattrbits); + } + + static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2AllGLCapabilities(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp) { + return wglARBPFIDs2GLCapabilitiesImpl(sharedCtx, hdc, pfdIDs, glp, GLGraphicsConfigurationUtil.ALL_BITS); + } + + private static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2GLCapabilitiesImpl(WindowsWGLContext sharedCtx, long hdc, int[] pfdIDs, + GLProfile glp, int winattrbits) { + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); + if (!haveWGLChoosePixelFormatARB) { + return null; + } + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); + final int numFormats = pfdIDs.length; + + int[] iattributes = new int [2*MAX_ATTRIBS]; + int[] iresults = new int [2*MAX_ATTRIBS]; + int niattribs = fillAttribsForGeneralWGLARBQuery(haveWGLARBMultisample, iattributes); + + ArrayList bucket = new ArrayList(); + + for(int i = 0; i<numFormats; i++) { + if ( pfdIDs[i] >= 1 && + sharedCtx.getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { + AttribList2GLCapabilities(bucket, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); + } else if (DEBUG) { + System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " + + i + "/" + numFormats + ": " + pfdIDs[i] + ", " + + GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); + } + } + return bucket; + } + + static boolean GLCapabilities2AttribList(GLCapabilitiesImmutable caps, + int[] iattributes, + GLContextImpl sharedCtx, + int accelerationValue, + int[] floatMode) throws GLException { + boolean haveWGLChoosePixelFormatARB = sharedCtx.isExtensionAvailable(WGL_ARB_pixel_format); + boolean haveWGLARBMultisample = sharedCtx.isExtensionAvailable(WGL_ARB_multisample); + if(DEBUG) { + System.err.println("HDC2GLCapabilities: ARB_pixel_format: "+haveWGLChoosePixelFormatARB); + System.err.println("HDC2GLCapabilities: ARB_multisample : "+haveWGLARBMultisample); + } + + if (!haveWGLChoosePixelFormatARB) { + return false; + } + + boolean onscreen = caps.isOnscreen(); + boolean pbuffer = caps.isPBuffer(); + + int niattribs = 0; + + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + if(accelerationValue>0) { + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; + iattributes[niattribs++] = accelerationValue; + } + if (onscreen) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else if (pbuffer) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + if (caps.getDoubleBuffered()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + if (caps.getStereo()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = caps.getDepthBits(); + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = caps.getRedBits(); + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAlphaBits(); + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = caps.getStencilBits(); + if (caps.getAccumRedBits() > 0 || + caps.getAccumGreenBits() > 0 || + caps.getAccumBlueBits() > 0 || + caps.getAccumAlphaBits() > 0) { + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB; + iattributes[niattribs++] = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits() + + caps.getAccumAlphaBits()); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = caps.getAccumRedBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getAccumGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getAccumBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAccumAlphaBits(); + } + + if (caps.getSampleBuffers() && haveWGLARBMultisample) { + iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; + iattributes[niattribs++] = caps.getNumSamples(); + } + + boolean rtt = caps.getPbufferRenderToTexture(); + boolean rect = caps.getPbufferRenderToTextureRectangle(); + boolean useFloat = caps.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 (!sharedCtx.isExtensionAvailable("GL_NV_texture_rectangle")) { + throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); + } + } + + if (useFloat) { + if (!sharedCtx.isExtensionAvailable("WGL_ATI_pixel_format_float") && + !sharedCtx.isExtensionAvailable("WGL_NV_float_buffer")) { + throw new GLException("Floating-point pbuffers not supported by this hardware"); + } + + // Prefer NVidia extension over ATI + if (sharedCtx.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_ARB; + } + } 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; + } + iattributes[niattribs++] = 0; + + return true; + } + + static int AttribList2DrawableTypeBits(final int[] iattribs, final int niattribs, final int[] iresults) { + int val = 0; + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.WINDOW_BIT; + break; + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.BITMAP_BIT; + break; + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + if(iresults[i] == GL.GL_TRUE) val |= GLGraphicsConfigurationUtil.PBUFFER_BIT; + break; + } + } + return val; + } + + static boolean AttribList2GLCapabilities( ArrayList capsBucket, + final GLProfile glp, final long hdc, final int pfdID, final int[] iattribs, + final int niattribs, + final int[] iresults, final int winattrmask) { + final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults); + int drawableTypeBits = winattrmask & allDrawableTypeBits; + + if( 0 == drawableTypeBits ) { + return false; + } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); + + if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + // remove displayable bits, since pfdID is non displayable + drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT); + if( 0 == drawableTypeBits ) { + return false; + } + // non displayable requested (pbuffer) + } + WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); + res.setValuesByARB(iattribs, niattribs, iresults); + + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits ); + } + + // + // GDI PIXELFORMAT + // + + static int[] wglAllGDIPFIDs(long hdc) { + int numFormats = GDI.DescribePixelFormat(hdc, 1, 0, null); + if (numFormats == 0) { + throw new GLException("DescribePixelFormat: No formats - HDC 0x" + Long.toHexString(hdc) + + ", LastError: " + GDI.GetLastError()); + } + int[] pfdIDs = new int[numFormats]; + for (int i = 0; i < numFormats; i++) { + pfdIDs[i] = 1 + i; + } + return pfdIDs; + } + + static int PFD2DrawableTypeBits(PIXELFORMATDESCRIPTOR pfd) { + int val = 0; + + int dwFlags = pfd.getDwFlags(); + + if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) { + val |= GLGraphicsConfigurationUtil.WINDOW_BIT; + } + if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) { + val |= GLGraphicsConfigurationUtil.BITMAP_BIT; + } + return val; + } + + static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) { + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); + ArrayList capsBucket = new ArrayList(1); + if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) { + return (WGLGLCapabilities) capsBucket.get(0); + } + return null; + } + + static boolean PFD2GLCapabilities(ArrayList capsBucket, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); + if(null == pfd) { + return false; + } + if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { + return false; + } + final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd); + final int drawableTypeBits = winattrmask & allDrawableTypeBits; + + if( 0 == drawableTypeBits ) { + return false; + } + + WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); + res.setValuesByGDI(); + + return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits ); + } + + static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + int pfdFlags = (GDI.PFD_SUPPORT_OPENGL | + GDI.PFD_GENERIC_ACCELERATED); + if (caps.getDoubleBuffered()) { + pfdFlags |= GDI.PFD_DOUBLEBUFFER; + } + if (caps.isOnscreen()) { + pfdFlags |= GDI.PFD_DRAW_TO_WINDOW; + } else { + pfdFlags |= GDI.PFD_DRAW_TO_BITMAP; + } + if (caps.getStereo()) { + pfdFlags |= GDI.PFD_STEREO; + } + pfd.setDwFlags(pfdFlags); + pfd.setIPixelType((byte) GDI.PFD_TYPE_RGBA); + pfd.setCColorBits((byte) colorDepth); + pfd.setCRedBits ((byte) caps.getRedBits()); + pfd.setCGreenBits((byte) caps.getGreenBits()); + pfd.setCBlueBits ((byte) caps.getBlueBits()); + pfd.setCAlphaBits((byte) caps.getAlphaBits()); + int accumDepth = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits()); + pfd.setCAccumBits ((byte) accumDepth); + pfd.setCAccumRedBits ((byte) caps.getAccumRedBits()); + pfd.setCAccumGreenBits((byte) caps.getAccumGreenBits()); + pfd.setCAccumBlueBits ((byte) caps.getAccumBlueBits()); + pfd.setCAccumAlphaBits((byte) caps.getAccumAlphaBits()); + pfd.setCDepthBits((byte) caps.getDepthBits()); + pfd.setCStencilBits((byte) caps.getStencilBits()); + pfd.setILayerType((byte) GDI.PFD_MAIN_PLANE); + + // n/a with non ARB/GDI method: + // multisample + // opaque + // pbuffer + return pfd; + } + + static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) { + PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); + pfd.setNSize((short) pfd.size()); + pfd.setNVersion((short) 1); + if(0 != hdc && 1 <= pfdID) { + if (GDI.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + // Accelerated pixel formats that are non displayable + if(DEBUG) { + System.err.println("Info: Non displayable pixel format " + pfdID + " of device context: error code " + GDI.GetLastError()); + } + return null; + } + } + return pfd; + } + + static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() { + return createPixelFormatDescriptor(0, 0); + } + + public String toString() { + return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + getPixelFormatID() + ", ARB-Choosen " + isChoosenByARB() + + ",\n\trequested " + getRequestedCapabilities() + + ",\n\tchosen " + getChosenCapabilities() + + "]"; + } +} + diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..a66d62485 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesChooser; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import com.jogamp.nativewindow.impl.windows.GDI; +import com.jogamp.nativewindow.impl.windows.PIXELFORMATDESCRIPTOR; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; +import com.jogamp.opengl.impl.GLGraphicsConfigurationUtil; +import com.jogamp.opengl.impl.SharedResourceRunner; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on Windows platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + static WGLGLCapabilities.PfdIDComparator PfdIDComparator = new WGLGLCapabilities.PfdIDComparator(); + + WindowsWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, this); + } + + protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + + if (! (capsChosen instanceof GLCapabilitiesImmutable) ) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen"); + } + + if (! (capsRequested instanceof GLCapabilitiesImmutable) ) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - requested"); + } + + return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, chooser, absScreen); + } + + static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLCapabilitiesImmutable caps, + AbstractGraphicsScreen absScreen) { + return chooseGraphicsConfigurationStatic(caps, caps, null, absScreen); + } + + static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen, + GLCapabilitiesImmutable capsReq, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if(null==absScreen) { + absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS); + } + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + + capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( + capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) ); + + return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser ); + } + + protected static List/*<WGLGLCapabilities>*/ getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) { + SharedResourceRunner.Resource sharedResource = factory.getOrCreateSharedResource(device); + if(null == sharedResource) { + throw new GLException("Shared resource for device n/a: "+device); + } + WindowsWGLDrawable sharedDrawable = (WindowsWGLDrawable) sharedResource.getDrawable(); + GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); + WindowsWGLContext sharedContext = (WindowsWGLContext) sharedResource.getContext(); + List availableCaps = null; + + sharedDrawable.lockSurface(); + try { + long hdc = sharedDrawable.getHandle(); + if (0 == hdc) { + throw new GLException("Error: HDC is null"); + } + if (sharedContext.isExtensionAvailable(WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format)) { + availableCaps = getAvailableGLCapabilitiesARB(hdc, sharedContext, capsChosen.getGLProfile()); + } + if( null == availableCaps || 0 == availableCaps.size() ) { + availableCaps = getAvailableGLCapabilitiesGDI(hdc, capsChosen); + } + } finally { + sharedDrawable.unlockSurface(); + } + + if( null != availableCaps ) { + Collections.sort(availableCaps, PfdIDComparator); + } + return availableCaps; + } + + static List/*<WGLGLCapabilities>*/ getAvailableGLCapabilitiesARB(long hdc, WindowsWGLContext sharedContext, GLProfile glProfile) { + int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedContext, hdc); + return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedContext, hdc, pformats, glProfile); + } + + static List/*<WGLGLCapabilities>*/ getAvailableGLCapabilitiesGDI(long hdc, GLCapabilitiesImmutable capsChosen) { + boolean onscreen = capsChosen.isOnscreen(); + if(capsChosen.isPBuffer()) { + return null; + } + GLProfile glProfile = capsChosen.getGLProfile(); + + int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); + int numFormats = pformats.length; + ArrayList bucket = new ArrayList(numFormats); + for (int i = 0; i < numFormats; i++) { + bucket.add( WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], onscreen) ); + } + return bucket; + } + + /** + * + * @param chooser + * @param _factory + * @param ns + * @param pfIDs optional pool of preselected PixelFormat IDs, maybe null for unrestricted selection + */ + static void updateGraphicsConfiguration(CapabilitiesChooser chooser, + GLDrawableFactory factory, NativeSurface ns, int[] pfdIDs) { + if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + if (factory == null) { + throw new IllegalArgumentException("GLDrawableFactory is null"); + } + if (ns == null) { + throw new IllegalArgumentException("NativeSurface is null"); + } + + if(NativeSurface.LOCK_SURFACE_NOT_READY >= ns.lockSurface()) { + throw new GLException("Surface not ready (lockSurface)"); + } + try { + long hdc = ns.getSurfaceHandle(); + if (0 == hdc) { + throw new GLException("Error: HDC is null"); + } + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) ns.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + + if(!config.isDetermined()) { + updateGraphicsConfiguration(config, chooser, factory, hdc, false, pfdIDs); + } else { + // set PFD if not set yet + int pfdID = -1; + boolean set = false; + if ( 1 > ( pfdID = GDI.GetPixelFormat(hdc) ) ) { + if (!GDI.SetPixelFormat(hdc, config.getPixelFormatID(), config.getPixelFormat())) { + throw new GLException("Unable to set pixel format " + config.getPixelFormatID() + + " for device context " + toHexString(hdc) + + ": error code " + GDI.GetLastError()); + } + set = true; + pfdID = config.getPixelFormatID(); + } + if (DEBUG) { + System.err.println("!!! setPixelFormat (post): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> "+pfdID+", set: "+set); + Thread.dumpStack(); + } + } + } finally { + ns.unlockSurface(); + } + } + + static void preselectGraphicsConfiguration(CapabilitiesChooser chooser, + GLDrawableFactory _factory, AbstractGraphicsDevice device, + WindowsWGLGraphicsConfiguration config, int[] pfdIDs) { + if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + if (_factory == null) { + throw new IllegalArgumentException("GLDrawableFactory is null"); + } + if (config == null) { + throw new IllegalArgumentException("WindowsWGLGraphicsConfiguration is null"); + } + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + WindowsWGLDrawable sharedDrawable = factory.getOrCreateSharedDrawable(device); + if(null == sharedDrawable) { + throw new IllegalArgumentException("Shared Drawable is null"); + } + + if(NativeSurface.LOCK_SURFACE_NOT_READY >= sharedDrawable.lockSurface()) { + throw new GLException("Surface not ready (lockSurface)"); + } + try { + long hdc = sharedDrawable.getHandle(); + if (0 == hdc) { + throw new GLException("Error: HDC is null"); + } + updateGraphicsConfiguration(config, chooser, factory, hdc, true, pfdIDs); + } finally { + sharedDrawable.unlockSurface(); + } + } + + private static void updateGraphicsConfiguration(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, + GLDrawableFactory factory, long hdc, boolean extHDC, int[] pfdIDs) { + if (DEBUG) { + if(extHDC) { + System.err.println("updateGraphicsConfiguration(using shared): hdc "+toHexString(hdc)); + } else { + System.err.println("updateGraphicsConfiguration(using target): hdc "+toHexString(hdc)); + } + System.err.println("!!! user chosen caps " + config.getChosenCapabilities()); + } + if( !updateGraphicsConfigurationARB(hdc, extHDC, config, chooser, (WindowsWGLDrawableFactory)factory, pfdIDs) ) { + updateGraphicsConfigurationGDI(hdc, extHDC, config, chooser, pfdIDs); + } + } + + private static boolean updateGraphicsConfigurationARB(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config, + CapabilitiesChooser chooser, WindowsWGLDrawableFactory factory, int[] pformats) { + AbstractGraphicsDevice device = config.getScreen().getDevice(); + WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContextImpl(device); + if (null == sharedContext) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: SharedContext is null: "+device); + } + return false; + } + if (!sharedContext.isExtensionAvailable(WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format)) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: "+WindowsWGLGraphicsConfiguration.WGL_ARB_pixel_format+" not available"); + } + return false; + } + + GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + boolean onscreen = capsChosen.isOnscreen(); + boolean usePBuffer = capsChosen.isPBuffer(); + GLProfile glProfile = capsChosen.getGLProfile(); + + WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps + boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] + final int presetPFDID = extHDC ? -1 : GDI.GetPixelFormat(hdc) ; + if ( 1 <= presetPFDID ) { + // Pixelformat already set by either + // - a previous preselectGraphicsConfiguration() call on the same HDC, + // - the graphics driver, copying the HDC's pixelformat to the new one, + // - or the Java2D/OpenGL pipeline's configuration + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: Pixel format already chosen for HDC: " + toHexString(hdc) + + ", pixelformat " + presetPFDID); + } + pixelFormatSet = true; + pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedContext, hdc, presetPFDID, glProfile, onscreen, usePBuffer); + } else { + int recommendedIndex = -1; // recommended index + + if(null == pformats) { + // No given PFD IDs + // + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice + int[] iattributes = new int[2 * WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + int accelerationMode = WGLExt.WGL_FULL_ACCELERATION_ARB; + pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedContext, capsChosen, + iattributes, accelerationMode, fattributes); + if (null == pformats) { + accelerationMode = WGLExt.WGL_GENERIC_ACCELERATION_ARB; + pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedContext, capsChosen, + iattributes, accelerationMode, fattributes); + } + if (null == pformats) { + accelerationMode = -1; // use what we are offered .. + pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedContext, capsChosen, + iattributes, accelerationMode, fattributes); + } + if (null != pformats) { + recommendedIndex = 0; + } else { + if(DEBUG) { + System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen); + } + // 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available + pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedContext, hdc); + if (DEBUG) { + final int len = ( null != pformats ) ? pformats.length : 0; + System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + len); + } + } + if (null == pformats) { + if (DEBUG) { + Thread.dumpStack(); + } + return false; + } + } + + List /*<WGLGLCapabilities>*/ availableCaps = + WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedContext, hdc, pformats, + glProfile, onscreen, usePBuffer); + if( null == availableCaps || 0 == availableCaps.size() ) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length + + " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer); + Thread.dumpStack(); + } + return false; + } + + if (DEBUG) { + System.err.println("updateGraphicsConfigurationARB: " + pformats.length + + " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer + ", " + availableCaps.size() + " glcaps"); + if(0 <= recommendedIndex) { + System.err.println("updateGraphicsConfigurationARB: Used wglChoosePixelFormatARB to recommend pixel format " + + pformats[recommendedIndex] + ", idx " + recommendedIndex +", "+availableCaps.get(recommendedIndex)); + } + } + + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { + if (DEBUG) { + Thread.dumpStack(); + } + return false; + } + pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex); + if( null == pixelFormatCaps) { + throw new GLException("Null Capabilities with "+ + " chosen pfdID: native recommended "+ (recommendedIndex+1) + + " chosen "+pixelFormatCaps.getPFDID()); + } + if (DEBUG) { + System.err.println("!!! chosen pfdID (ARB): native recommended "+ (recommendedIndex+1) + + " chosen "+pixelFormatCaps); + } + } + + if ( !extHDC && !pixelFormatSet ) { + if (!GDI.SetPixelFormat(hdc, pixelFormatCaps.getPFDID(), pixelFormatCaps.getPFD())) { + throw new GLException("Unable to set pixel format " + pixelFormatCaps.getPFDID() + + " for device context " + toHexString(hdc) + + ": error code " + GDI.GetLastError()); + } + if (DEBUG) { + System.err.println("!!! setPixelFormat (ARB): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> "+pixelFormatCaps.getPFDID()); + } + } + config.setCapsPFD(pixelFormatCaps); + return true; + } + + private static boolean updateGraphicsConfigurationGDI(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config, + CapabilitiesChooser chooser, int[] pformats) { + GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + if(capsChosen.isPBuffer()) { + if (DEBUG) { + System.err.println("updateGraphicsConfigurationGDI: no pbuffer supported on GDI: " + capsChosen); + } + return false; + } + boolean onscreen = capsChosen.isOnscreen(); + GLProfile glProfile = capsChosen.getGLProfile(); + + ArrayList/*<WGLGLCapabilities>*/ availableCaps = new ArrayList(); + int pfdID; // chosen or preset PFD ID + WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps + boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] + + if ( !extHDC && 1 <= ( pfdID = GDI.GetPixelFormat(hdc) ) ) { + // Pixelformat already set by either + // - a previous preselectGraphicsConfiguration() call on the same HDC, + // - the graphics driver, copying the HDC's pixelformat to the new one, + // - or the Java2D/OpenGL pipeline's configuration + if (DEBUG) { + System.err.println("updateGraphicsConfigurationGDI: NOTE: pixel format already chosen for HDC: " + toHexString(hdc) + + ", pixelformat " + pfdID); + } + pixelFormatSet = true; + pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, onscreen); + } else { + if(null == pformats) { + pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); + } + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false); + + for (int i = 0; i < pformats.length; i++) { + WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask); + } + + // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capsChosen, pfd); + pfdID = GDI.ChoosePixelFormat(hdc, pfd); + int recommendedIndex = -1 ; + if( 1 <= pfdID ) { + // seek index .. + for (recommendedIndex = availableCaps.size() - 1 ; + 0 <= recommendedIndex && pfdID != ((WGLGLCapabilities) availableCaps.get(recommendedIndex)).getPFDID(); + recommendedIndex--) + { /* nop */ } + } + // 2nd choice: if no preferred recommendedIndex available + if (DEBUG) { + System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = " + pfdID + ", idx " + recommendedIndex + " (LastError: " + GDI.GetLastError() + ")"); + } + int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex); + if ( 0 > chosenIndex ) { + if (DEBUG) { + Thread.dumpStack(); + } + return false; + } + pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex); + if (DEBUG) { + System.err.println("!!! chosen pfdID (GDI): native recommended "+ (recommendedIndex+1) + + ", caps " + pixelFormatCaps); + } + } + + if ( !extHDC && !pixelFormatSet ) { + if (!GDI.SetPixelFormat(hdc, pixelFormatCaps.getPFDID(), pixelFormatCaps.getPFD())) { + throw new GLException("Unable to set pixel format " + pixelFormatCaps.getPFDID() + + " for device context " + toHexString(hdc) + + ": error code " + GDI.GetLastError()); + } + if (DEBUG) { + System.err.println("!!! setPixelFormat (GDI): hdc "+toHexString(hdc) +", "+config.getPixelFormatID()+" -> " + pixelFormatCaps.getPFDID()); + } + } + config.setCapsPFD(pixelFormatCaps); + return true; + } +} + diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..f753c08c5 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. 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. + */ + +package com.jogamp.opengl.impl.windows.wgl.awt; + + +import com.jogamp.common.util.ArrayHashSet; +import com.jogamp.nativewindow.impl.jawt.windows.Win32SunJDKReflection; +import com.jogamp.opengl.impl.GLGraphicsConfigurationFactory; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesChooser; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; +import javax.media.nativewindow.awt.AWTGraphicsDevice; +import javax.media.nativewindow.awt.AWTGraphicsScreen; +import javax.media.nativewindow.windows.WindowsGraphicsDevice; + +import javax.media.opengl.GLCapabilitiesChooser; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; + +import com.jogamp.opengl.impl.windows.wgl.WindowsWGLGraphicsConfiguration; +import javax.media.opengl.GLDrawableFactory; + +public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public WindowsAWTWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl( + CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, + CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1, AbstractGraphicsDevice.DEFAULT_UNIT); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: creating default device: "+absScreen); + } + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if ( !(capsChosen instanceof GLCapabilitiesImmutable) ) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects - chosen"); + } + + if ( !(capsRequested instanceof GLCapabilitiesImmutable) ) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects - requested"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: got "+absScreen); + } + + WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex()); + GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice); + GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory( ((GLCapabilitiesImmutable)capsChosen).getGLProfile() ); + + WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration) + configFactory.chooseGraphicsConfiguration(capsChosen, + capsRequested, + chooser, winScreen); + if (winConfig == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen); + } + + GraphicsConfiguration chosenGC = null; + + // 1st Choice: Create an AWT GraphicsConfiguration with the desired PFD + // This gc will probably not be able to support GDI (WGL_SUPPORT_GDI_ARB, PFD_SUPPORT_GDI) + // however on most GPUs this is the current situation for Windows, + // otherwise no hardware accelerated PFD could be achieved. + // - preselect with no constrains + // - try to create dedicated GC + winConfig.preselectGraphicsConfiguration(drawableFactory, null); + if ( 1 <= winConfig.getPixelFormatID() ) { + chosenGC = Win32SunJDKReflection.graphicsConfigurationGet(device, winConfig.getPixelFormatID()); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found new AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + } + } + + if( null == chosenGC ) { + // 2nd Choice: Choose and match the GL Visual with AWT: + // - collect all AWT PFDs + // - choose a GL config from the pool of AWT PFDs + // + // The resulting GraphicsConfiguration has to be 'forced' on the AWT native peer, + // ie. returned by GLCanvas's getGraphicsConfiguration() befor call by super.addNotify(). + // + + // collect all available PFD IDs + GraphicsConfiguration[] configs = device.getConfigurations(); + int[] pfdIDs = new int[configs.length]; + ArrayHashSet pfdIDOSet = new ArrayHashSet(); + for (int i = 0; i < configs.length; i++) { + GraphicsConfiguration gc = configs[i]; + pfdIDs[i] = Win32SunJDKReflection.graphicsConfigurationGetPixelFormatID(gc); + pfdIDOSet.add(new Integer(pfdIDs[i])); + if(DEBUG) { + System.err.println("AWT pfd["+i+"] "+pfdIDs[i]); + } + } + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: PFD IDs: "+pfdIDs.length+", unique: "+pfdIDOSet.size()); + } + winConfig.preselectGraphicsConfiguration(drawableFactory, pfdIDs); + int gcIdx = pfdIDOSet.indexOf(new Integer(winConfig.getPixelFormatID())); + if( 0 > gcIdx ) { + chosenGC = configs[gcIdx]; + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: Found matching AWT PFD ID "+winConfig.getPixelFormatID()+" -> "+winConfig); + } + } + } + + if ( null == chosenGC ) { + throw new GLException("Unable to determine GraphicsConfiguration: "+winConfig); + } + return new AWTGraphicsConfiguration(awtScreen, winConfig.getChosenCapabilities(), winConfig.getRequestedCapabilities(), + chosenGC, winConfig); + } +} |