From 61a47e07975eb2fd8b1f5f60552935c993a6eef6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 17 Apr 2013 15:03:46 +0200 Subject: Bug 718: Windows BITMAP Offscreen Fails w/ GLCaps other than simple RGB888 - Filter invalid PFD configs - Filter invalid PFD configs - WindowsBitmapWGLDrawable: Clip chosenCaps to RGBA888[0|8] - WindowsBitmapWGLDrawable: Only use BITMAPINFOHEADER.BiBitCount=24 - WindowsWGLGraphicsConfiguration: Only allow GDI BITMAP PFD's w/ RGB888 w/ alpha <= red, others may fail - WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilities() - Fetch ARB caps w/o BITMAP - Concat GDI [BITMAP] caps --- .../windows/wgl/WindowsBitmapWGLDrawable.java | 44 ++++++++++++++-------- .../wgl/WindowsWGLGraphicsConfiguration.java | 15 +++++++- .../WindowsWGLGraphicsConfigurationFactory.java | 23 +++++++---- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java index 6993191f6..bd018105a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -50,6 +50,7 @@ import javax.media.opengl.GLException; import jogamp.nativewindow.windows.BITMAPINFO; import jogamp.nativewindow.windows.BITMAPINFOHEADER; import jogamp.nativewindow.windows.GDI; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.nio.PointerBuffer; @@ -77,24 +78,37 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { private void createBitmap() { int werr; - NativeSurface ns = getNativeSurface(); + final NativeSurface ns = getNativeSurface(); if(DEBUG) { System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (1): "+ns); } - WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); - GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); - int width = getWidth(); - int height = getHeight(); + final WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); + final GLCapabilitiesImmutable capsChosen; + { + final GLCapabilitiesImmutable capsChosen0 = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + capsChosen = GLGraphicsConfigurationUtil.clipRGBAGLCapabilities(capsChosen0, false /* allowRGB555 */); + if( capsChosen0 != capsChosen ) { + config.setChosenCapabilities(capsChosen); + if(DEBUG) { + System.err.println("WindowsBitmapWGLDrawable: "+capsChosen0+" -> "+capsChosen); + } + } + } + final int width = getWidth(); + final 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()); + final BITMAPINFO info = BITMAPINFO.create(); + final BITMAPINFOHEADER header = info.getBmiHeader(); + final int bitsPerPixelIn = capsChosen.getRedBits() + + capsChosen.getGreenBits() + + capsChosen.getBlueBits(); + final int bitsPerPixel; + // Note: For BITMAP 32 bpp, the high-byte is _not_ used and hence maximum color is RGB888! + // Note: For BITAMP a biBitCount value other than 24 (RGB888) usually does not work! + bitsPerPixel = 24; // RGB888 only! header.setBiSize(BITMAPINFOHEADER.size()); header.setBiWidth(width); // NOTE: negating the height causes the DIB to be in top-down row @@ -108,21 +122,21 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { header.setBiClrUsed(0); header.setBiClrImportant(0); header.setBiCompression(GDI.BI_RGB); - int byteNum = width * height * ( bitsPerPixel >> 3 ) ; + final int byteNum = width * height * ( bitsPerPixel >> 3 ) ; header.setBiSizeImage(byteNum); - PointerBuffer pb = PointerBuffer.allocateDirect(1); + final 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 + + ", bpp " + bitsPerPixelIn + " -> " + bitsPerPixel + ", bytes " + byteNum + ", header sz " + BITMAPINFOHEADER.size() + ", DIB ptr num " + pb.capacity()+ - ", "+capabilities+ + ", "+capsChosen+ ", werr "+werr); } if (hbitmap == 0) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 7709e5884..fdff20daa 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -684,15 +684,28 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio if(null == pfd) { return null; } - if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { + if ( (pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) { return null; } final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd); final int drawableTypeBits = winattrmask & allDrawableTypeBits; if( 0 == drawableTypeBits ) { + if(DEBUG) { + System.err.println("Drop [drawableType mismatch]: " + WGLGLCapabilities.PFD2String(pfd, pfdID)); + } return null; } + if( GLGraphicsConfigurationUtil.BITMAP_BIT == drawableTypeBits ) { + // BITMAP exclusive PFD SafeGuard: Only accept BITMAP compatible color formats! + final int pfdColorBits = pfd.getCColorBits(); + if ( pfdColorBits != 24 || pfd.getCRedBits() < pfd.getCAlphaBits() ) { // Allowed: RGB888 && alpha <= red + if(DEBUG) { + System.err.println("Drop [color bits excl BITMAP]: " + WGLGLCapabilities.PFD2String(pfd, pfdID)); + } + return null; + } + } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 8c5ea12d5..62a21922f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -139,8 +139,12 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat if (sharedResource.hasARBPixelFormat()) { availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc); } - if( null == availableCaps || availableCaps.isEmpty() ) { - availableCaps = getAvailableGLCapabilitiesGDI(device, glp, hdc); + final boolean hasARBCaps = null != availableCaps && !availableCaps.isEmpty() ; + final List availableCapsGDI = getAvailableGLCapabilitiesGDI(device, glp, hdc, hasARBCaps); + if( !hasARBCaps ) { + availableCaps = availableCapsGDI; + } else { + availableCaps.addAll(availableCapsGDI); } } finally { if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -156,18 +160,20 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat return availableCaps; } - static List getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, long hdc) { + private static List getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, long hdc) { final int pfdIDCount = WindowsWGLGraphicsConfiguration.wglARBPFDIDCount((WindowsWGLContext)sharedResource.getContext(), hdc); final int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFDIDs(pfdIDCount); - return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, GLGraphicsConfigurationUtil.ALL_BITS); + return WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, device, glProfile, hdc, pformats, + GLGraphicsConfigurationUtil.ALL_BITS & ~GLGraphicsConfigurationUtil.BITMAP_BIT); // w/o BITMAP } - static List getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc) { + private static List getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc, boolean bitmapOnly) { int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc); int numFormats = pformats.length; List bucket = new ArrayList(numFormats); for (int i = 0; i < numFormats; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); + final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], + bitmapOnly ? GLGraphicsConfigurationUtil.BITMAP_BIT : GLGraphicsConfigurationUtil.ALL_BITS ); if(null != caps) { bucket.add(caps); } @@ -484,7 +490,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat List availableCaps = new ArrayList(); for (int i = 0; i < pformats.length; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask); + final WGLGLCapabilities caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask); if(null != caps) { availableCaps.add(caps); if(DEBUG) { @@ -528,7 +534,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex); if (DEBUG) { - System.err.println("chosen pfdID (GDI): chosenIndex "+ chosenIndex + ", caps " + pixelFormatCaps); + System.err.println("chosen pfdID (GDI): chosenIndex "+ chosenIndex + ", caps " + pixelFormatCaps + + " (" + WGLGLCapabilities.PFD2String(pixelFormatCaps.getPFD(), pixelFormatCaps.getPFDID()) +")"); } } -- cgit v1.2.3