/* * 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 jogamp.opengl.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 jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; import jogamp.opengl.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 = jogamp.opengl.Debug.debug("GraphicsConfiguration"); protected static final int MAX_PFORMATS = 256; protected static final int MAX_ATTRIBS = 256; private GLCapabilitiesChooser chooser; private boolean isDetermined = false; private boolean isExternal = false; WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { super(screen, capsChosen, capsRequested); this.chooser=chooser; this.isDetermined = false; } WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, WGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested) { super(screen, capsChosen, capsRequested); setCapsPFD(capsChosen); this.chooser=null; } static WindowsWGLGraphicsConfiguration createFromExternal(GLDrawableFactory _factory, long hdc, int pfdID, GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen) { 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(); WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat(); WGLGLCapabilities caps = null; if(hasARB) { caps = wglARBPFID2GLCapabilities(sharedResource, hdc, pfdID, glp, onscreen, true /* pbuffer */); } else { caps = PFD2GLCapabilities(glp, hdc, pfdID, onscreen); } if(null==caps) { throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+ ", pfdID "+pfdID+", onscreen "+onscreen+", hasARB "+hasARB); } WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps); cfg.markExternal(); return cfg; } public Object clone() { return super.clone(); } /** * Updates the graphics configuration in case it has been determined yet.
* Uses the NativeSurface's HDC.
* 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() * @see #isExternal() */ 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.
* 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); } /** * Sets the hdc's PixelFormat, this configuration's capabilities and marks it as determined. */ final void setPixelFormat(long hdc, WGLGLCapabilities caps) { if (0 == hdc) { throw new GLException("Error: HDC is null"); } if (!GDI.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) { throw new GLException("Unable to set pixel format " + caps + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); } if (DEBUG) { System.err.println("!!! setPixelFormat (ARB): hdc "+toHexString(hdc) +", "+caps); } setCapsPFD(caps); } /** * Only sets this configuration's capabilities and marks it as determined, * the actual pixelformat is not set. */ final void setCapsPFD(WGLGLCapabilities caps) { setChosenCapabilities(caps); this.isDetermined = true; if (DEBUG) { System.err.println("*** setCapsPFD: "+caps); } } /** * External configuration's HDC pixelformat shall not be modified */ public final boolean isExternal() { return isExternal; } final void markExternal() { this.isExternal=true; } /** * Determined configuration states set target capabilties via {@link #setCapsPFD(WGLGLCapabilities)}, * but does not imply a set pixelformat. * * @see #setPixelFormat(long, WGLGLCapabilities) * @see #setCapsPFD(WGLGLCapabilities) */ public final boolean isDetermined() { return isDetermined; } public final PIXELFORMATDESCRIPTOR getPixelFormat() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).getPFD() : null; } public final int getPixelFormatID() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).getPFDID() : 0; } public final boolean isChoosenByARB() { return isDetermined ? ((WGLGLCapabilities)capabilitiesChosen).isSetByARB() : false; } static int fillAttribsForGeneralWGLARBQuery(WindowsWGLDrawableFactory.SharedResource sharedResource, int[] iattributes) { int niattribs = 0; iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; if(sharedResource.hasARBPBuffer()) { 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(sharedResource.hasARBMultisample()) { iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; } if(sharedResource.hasARBPBuffer()) { WindowsWGLContext sharedCtx = sharedResource.getContext(); if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) { // pbo float buffer 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(WindowsWGLDrawableFactory.SharedResource sharedResource, long hdc, int pfdID, GLProfile glp, boolean onscreen, boolean usePBuffer) { if (!sharedResource.hasARBPixelFormat()) { return null; } int[] iattributes = new int [2*MAX_ATTRIBS]; int[] iresults = new int [2*MAX_ATTRIBS]; int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes); if (!sharedResource.getContext().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 " + toHexString(hdc) + ", werr " + GDI.GetLastError()); } 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, WindowsWGLDrawableFactory.SharedResource sharedResource, GLCapabilitiesImmutable capabilities, int[] iattributes, int accelerationMode, float[] fattributes) { if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, iattributes, sharedResource, 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 ( !sharedResource.getContext().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( sharedResource, hdc, pformats[i], capabilities.getGLProfile(), capabilities.isOnscreen(), capabilities.isPBuffer()); System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps0); } } return pformats; } static List /**/ wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource, long hdc, int[] pfdIDs, GLProfile glp, boolean onscreen, boolean usePBuffer) { final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, winattrbits); } static List /**/ wglARBPFIDs2AllGLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource, long hdc, int[] pfdIDs, GLProfile glp) { return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, GLGraphicsConfigurationUtil.ALL_BITS); } private static List /**/ wglARBPFIDs2GLCapabilitiesImpl(WindowsWGLDrawableFactory.SharedResource sharedResource, long hdc, int[] pfdIDs, GLProfile glp, int winattrbits) { if (!sharedResource.hasARBPixelFormat()) { return null; } final int numFormats = pfdIDs.length; int[] iattributes = new int [2*MAX_ATTRIBS]; int[] iresults = new int [2*MAX_ATTRIBS]; int niattribs = fillAttribsForGeneralWGLARBQuery(sharedResource, iattributes); ArrayList bucket = new ArrayList(); for(int i = 0; i= 1 && sharedResource.getContext().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, WindowsWGLDrawableFactory.SharedResource sharedResource, int accelerationValue, int[] floatMode) throws GLException { if (!sharedResource.hasARBPixelFormat()) { 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 && sharedResource.hasARBPBuffer()) { 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() && sharedResource.hasARBMultisample()) { 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; boolean nvidia = false; if (pbuffer && sharedResource.hasARBPBuffer()) { // 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"); } WindowsWGLContext sharedCtx = sharedResource.getContext(); if (rect) { if (!sharedCtx.isExtensionAvailable("GL_NV_texture_rectangle")) { throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); } } if (useFloat) { // Prefer NVidia extension over ATI nvidia = sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer); if(nvidia) { floatMode[0] = GLPbuffer.NV_FLOAT; } else { ati = sharedCtx.isExtensionAvailable("WGL_ATI_pixel_format_float"); if(ati) { floatMode[0] = GLPbuffer.ATI_FLOAT; } else { throw new GLException("Floating-point pbuffers not supported by this hardware"); } } if (DEBUG) { System.err.println("Using " + (ati ? "ATI" : ( nvidia ? "NVidia" : "NONE" ) ) + " 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 && nvidia) { iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; iattributes[niattribs++] = GL.GL_TRUE; } if (rtt) { if (useFloat) { assert(!ati); assert(nvidia); 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() + "]"; } }