/* * 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.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.MutableGraphicsConfiguration; import com.jogamp.opengl.GLExtensions; import jogamp.nativewindow.windows.DWM_BLURBEHIND; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.MARGINS; import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; @SuppressWarnings("deprecation") public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { 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, device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } else { caps = PFD2GLCapabilities(device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } 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 = 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 (!WGLUtil.SetPixelFormat(hdc, caps.getPFDID(), caps.getPFD())) { throw new GLException("Unable to set pixel format " + caps.getPFDID() + " of " + caps + " for device context " + toHexString(hdc) + ": error code " + GDI.GetLastError()); } if(!caps.isBackgroundOpaque()) { final long hwnd = GDI.WindowFromDC(hdc); DWM_BLURBEHIND bb = DWM_BLURBEHIND.create(); bb.setDwFlags(GDI.DWM_BB_ENABLE); bb.setFEnable(1); boolean ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb); if(ok) { MARGINS m = MARGINS.create(); m.setCxLeftWidth(-1); m.setCxRightWidth(-1); m.setCyBottomHeight(-1); m.setCyTopHeight(-1); ok = GDI.DwmExtendFrameIntoClientArea(hwnd, m); } if(DEBUG) { System.err.println("translucency enabled on wnd: 0x"+Long.toHexString(hwnd)+" - ok: "+ok); } } if (DEBUG) { System.err.println("setPixelFormat: 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()) { GLContextImpl 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 wglARBPFDIDCount(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; // pfdID shall be ignored here (spec), however, pass a valid pdf index '1' below (possible driver bug) if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 1 /* pfdID */, 0, 1, iattributes, 0, iresults, 0)) { if(DEBUG) { System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) + ", value "+iresults[0]+ ", LastError: " + GDI.GetLastError()); Thread.dumpStack(); } return 0; } final int pfdIDCount = iresults[0]; if(0 == pfdIDCount) { if(DEBUG) { System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) + ", LastError: " + GDI.GetLastError()); Thread.dumpStack(); } } return pfdIDCount; } static int[] wglAllARBPFDIDs(int pfdIDCount) { int[] pfdIDs = new int[pfdIDCount]; for (int i = 0; i < pfdIDCount; i++) { pfdIDs[i] = 1 + i; } return pfdIDs; } static WGLGLCapabilities wglARBPFID2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glp, long hdc, int pfdID, int winattrbits) { 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 (!((WindowsWGLContext)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()); } return AttribList2GLCapabilities(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits); } static int[] wglChoosePixelFormatARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, long hdc, 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 ( !((WindowsWGLContext)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, device, capabilities.getGLProfile(), hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps0); } } return pformats; } static List wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glp, long hdc, int[] pfdIDs, 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 && ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); if(null != caps) { bucket.add(caps); if(DEBUG) { final int j = bucket.size() - 1; System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> "+j+"]: "+caps); } } else if(DEBUG) { GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS); System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> skip]: pfdID "+pfdIDs[i]+", "+skipped+", winattr "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); } } else if (DEBUG) { if( 1 > pfdIDs[i] ) { System.err.println("wglARBPFIDs2GLCapabilities: Invalid pfdID " + i + "/" + numFormats + ": " + pfdIDs[i]); } else { System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " + i + "/" + numFormats + ": " + pfdIDs[i] + ", hdc " + toHexString(hdc)); } } } return bucket; } static boolean GLCapabilities2AttribList(GLCapabilitiesImmutable caps, int[] iattributes, WindowsWGLDrawableFactory.SharedResource sharedResource, int accelerationValue, int[] floatMode) throws GLException { if (!sharedResource.hasARBPixelFormat()) { return false; } 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; } final boolean usePBuffer = caps.isPBuffer() && sharedResource.hasARBPBuffer() ; final int surfaceType; if( caps.isOnscreen() ) { surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB; } else if( caps.isFBO() ) { surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB; // native replacement! } else if( usePBuffer ) { surfaceType = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; } else if( caps.isBitmap() ) { surfaceType = WGLExt.WGL_DRAW_TO_BITMAP_ARB; } else { throw new GLException("no surface type set in caps: "+caps); } iattributes[niattribs++] = surfaceType; 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_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(); if(caps.getAlphaBits()>0) { iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; iattributes[niattribs++] = caps.getAlphaBits(); } if(caps.getStencilBits()>0) { iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; iattributes[niattribs++] = caps.getStencilBits(); } iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; iattributes[niattribs++] = caps.getDepthBits(); 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 ( usePBuffer ) { // 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"); } GLContextImpl sharedCtx = sharedResource.getContext(); if (rect) { if (!sharedCtx.isExtensionAvailable(GLExtensions.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 | GLGraphicsConfigurationUtil.FBO_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 WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device, 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 null; } PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) { // remove displayable bits, since pfdID is non displayable drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT | GLGraphicsConfigurationUtil.FBO_BIT ); if( 0 == drawableTypeBits ) { return null; } // non displayable requested (pbuffer) } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByARB(iattribs, niattribs, iresults); return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } // // GDI PIXELFORMAT // static int[] wglAllGDIPFIDs(long hdc) { int numFormats = WGLUtil.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 | GLGraphicsConfigurationUtil.FBO_BIT; } if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) { val |= GLGraphicsConfigurationUtil.BITMAP_BIT; } return val; } static WGLGLCapabilities PFD2GLCapabilities(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); if(null == pfd) { return null; } if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { return null; } final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd); final int drawableTypeBits = winattrmask & allDrawableTypeBits; if( 0 == drawableTypeBits ) { return null; } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); return PFD2GLCapabilitiesNoCheck(device, glp, pfd, pfdID); } static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) { if(null == pfd) { return null; } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res); } 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.isOnscreen() ) { pfdFlags |= GDI.PFD_DRAW_TO_WINDOW; } else if( caps.isFBO() ) { pfdFlags |= GDI.PFD_DRAW_TO_WINDOW; // native replacement! } else if( caps.isPBuffer() ) { pfdFlags |= GDI.PFD_DRAW_TO_BITMAP; // pbuffer n/a, use bitmap } else if( caps.isBitmap() ) { pfdFlags |= GDI.PFD_DRAW_TO_BITMAP; } else { throw new GLException("no surface type set in caps: "+caps); } if ( caps.getDoubleBuffered() ) { if( caps.isBitmap() || caps.isPBuffer() ) { pfdFlags |= GDI.PFD_DOUBLEBUFFER_DONTCARE; // bitmaps probably don't have dbl buffering } else { pfdFlags |= GDI.PFD_DOUBLEBUFFER; } } 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) PIXELFORMATDESCRIPTOR.size()); pfd.setNVersion((short) 1); if(0 != hdc && 1 <= pfdID) { if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.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() + "]"; } }