summaryrefslogtreecommitdiffstats
path: root/src/net/java/games/jogl/impl/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/games/jogl/impl/windows')
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContext.java36
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java261
-rw-r--r--src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java2
3 files changed, 230 insertions, 69 deletions
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
index 0dd05f7ba..eed383794 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContext.java
@@ -40,7 +40,9 @@
package net.java.games.jogl.impl.windows;
import java.awt.Component;
+import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
import java.util.*;
import net.java.games.gluegen.runtime.*; // for PROCADDRESS_VAR_PREFIX
import net.java.games.jogl.*;
@@ -138,7 +140,7 @@ public abstract class WindowsGLContext extends GLContext {
}
if (!WGL.wglMakeCurrent(hdc, hglrc)) {
- throw new GLException("Error making context current");
+ throw new GLException("Error making context current: " + WGL.GetLastError());
}
if (created) {
@@ -164,7 +166,7 @@ public abstract class WindowsGLContext extends GLContext {
protected synchronized void free() throws GLException {
if (!WGL.wglMakeCurrent(0, 0)) {
- throw new GLException("Error freeing OpenGL context");
+ throw new GLException("Error freeing OpenGL context: " + WGL.GetLastError());
}
}
@@ -270,10 +272,11 @@ public abstract class WindowsGLContext extends GLContext {
GLCapabilities[] availableCaps = null;
int numFormats = 0;
pfd = newPixelFormatDescriptor();
- GraphicsDevice device = component.getGraphicsConfiguration().getDevice();
+ GraphicsConfiguration config = component.getGraphicsConfiguration();
+ GraphicsDevice device = config.getDevice();
// Produce a recommended pixel format selection for the GLCapabilitiesChooser.
// Try to use wglChoosePixelFormatARB if we have it available
- GL dummyGL = WindowsGLContextFactory.getDummyGLContext(device);
+ GL dummyGL = WindowsGLContextFactory.getDummyGL(device);
int recommendedPixelFormat = -1;
boolean haveWGLChoosePixelFormatARB = false;
boolean haveWGLARBMultisample = false;
@@ -286,6 +289,19 @@ public abstract class WindowsGLContext extends GLContext {
}
}
}
+ Rectangle rect = config.getBounds();
+ long dc = 0;
+ long rc = 0;
+ boolean freeWGLC = false;
+ if( dummyGL != null ) {
+ dc = WindowsGLContextFactory.getDummyGLContext( device ).hdc;
+ rc = WindowsGLContextFactory.getDummyGLContext( device ).hglrc;
+ if( !WGL.wglMakeCurrent( dc, rc ) ) {
+ System.err.println("Error Making WGLC Current: " + WGL.GetLastError() );
+ } else {
+ freeWGLC = true;
+ }
+ }
if (dummyGL != null && haveWGLChoosePixelFormatARB) {
int[] iattributes = new int [2 * MAX_ATTRIBS];
int[] iresults = new int [2 * MAX_ATTRIBS];
@@ -365,6 +381,11 @@ public abstract class WindowsGLContext extends GLContext {
System.err.println("Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat);
}
}
+ } else {
+ if (DEBUG) {
+ System.err.println("wglChoosePixelFormatARB failed: " + WGL.GetLastError() );
+ Thread.dumpStack();
+ }
}
if (DEBUG) {
if (recommendedPixelFormat < 0) {
@@ -388,7 +409,7 @@ public abstract class WindowsGLContext extends GLContext {
niattribs = 0;
iattributes[0] = GL.WGL_NUMBER_PIXEL_FORMATS_ARB;
if (!dummyGL.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, iresults)) {
- throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB");
+ throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: " + WGL.GetLastError());
}
numFormats = iresults[0];
// Should we be filtering out the pixel formats which aren't
@@ -423,6 +444,9 @@ public abstract class WindowsGLContext extends GLContext {
}
availableCaps[i] = iattributes2GLCapabilities(iattributes, iresults, niattribs, true);
}
+ if( freeWGLC ) {
+ WGL.wglMakeCurrent( 0, 0 );
+ }
} else {
if (DEBUG) {
System.err.println("Using ChoosePixelFormat because no wglChoosePixelFormatARB: dummyGL = " + dummyGL);
@@ -456,7 +480,7 @@ public abstract class WindowsGLContext extends GLContext {
}
pixelFormat += 1; // one-base the index
if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) {
- throw new GLException("Error re-describing the chosen pixel format");
+ throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError());
}
} else {
// For now, use ChoosePixelFormat for offscreen surfaces until
diff --git a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
index 74d72645d..6603dc2eb 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsGLContextFactory.java
@@ -40,15 +40,16 @@
package net.java.games.jogl.impl.windows;
import java.awt.Component;
-import java.awt.Dialog;
-import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.Collection;
+import java.util.Iterator;
import net.java.games.jogl.*;
import net.java.games.jogl.impl.*;
@@ -68,6 +69,10 @@ public class WindowsGLContextFactory extends GLContextFactory {
private static Map/*<GraphicsDevice, String>*/ dummyExtensionsMap = new HashMap();
private static Set/*<GraphicsDevice >*/ pendingContextSet = new HashSet();
+ public WindowsGLContextFactory() {
+ Runtime.getRuntime().addShutdownHook( new ShutdownHook() );
+ }
+
public GraphicsConfiguration chooseGraphicsConfiguration(GLCapabilities capabilities,
GLCapabilitiesChooser chooser,
GraphicsDevice device) {
@@ -84,80 +89,212 @@ public class WindowsGLContextFactory extends GLContextFactory {
return new WindowsOffscreenGLContext(capabilities, chooser, shareWith);
}
}
+
+ // Return cached GL context
+ public static WindowsGLContext getDummyGLContext( final GraphicsDevice device ) {
+ checkForDummyContext( device );
+ NativeWindowStruct nws = (NativeWindowStruct) dummyContextMap.get(device);
+ return nws.getWindowsContext();
+ }
+ // Return cached extension string
public static String getDummyGLExtensions(final GraphicsDevice device) {
- String exts = (String) dummyExtensionsMap.get(device);
- return (exts == null) ? "" : exts;
+ checkForDummyContext( device );
+ String exts = (String) dummyExtensionsMap.get(device);
+ return (exts == null) ? "" : exts;
}
- public static GL getDummyGLContext(final GraphicsDevice device) {
- GL gl = (GL) dummyContextMap.get(device);
- if (gl != null) {
- return gl;
- }
+ // Return cached GL function pointers
+ public static GL getDummyGL(final GraphicsDevice device) {
+ checkForDummyContext( device );
+ NativeWindowStruct nws = (NativeWindowStruct) dummyContextMap.get(device);
+ return( nws.getWindowsContext().getGL() );
+ }
- if (!pendingContextSet.contains(device)) {
+ /*
+ * Locate a cached native window, if one doesn't exist create one amd
+ * cache it.
+ */
+ private static void checkForDummyContext( final GraphicsDevice device ) {
+ if (!pendingContextSet.contains(device) && !dummyContextMap.containsKey( device ) ) {
pendingContextSet.add(device);
GraphicsConfiguration config = device.getDefaultConfiguration();
- final Dialog frame = new Dialog(new Frame(config), "", false, config);
- frame.setUndecorated(true);
- final GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities(),
- null,
- null,
- device);
- canvas.addGLEventListener(new GLEventListener() {
- public void init(GLDrawable drawable) {
- pendingContextSet.remove(device);
- dummyContextMap.put(device, drawable.getGL());
- String availableGLExtensions = "";
- String availableWGLExtensions = "";
- String availableEXTExtensions = "";
- try {
- availableWGLExtensions = drawable.getGL().wglGetExtensionsStringARB(WGL.wglGetCurrentDC());
- } catch (GLException e) {}
- try {
- availableEXTExtensions = drawable.getGL().wglGetExtensionsStringEXT();
- } catch (GLException e) {}
- availableGLExtensions = drawable.getGL().glGetString(GL.GL_EXTENSIONS);
- dummyExtensionsMap.put(device, availableGLExtensions + " " + availableEXTExtensions + " " + availableWGLExtensions);
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- frame.dispose();
- }
- });
- }
+ Rectangle rect = config.getBounds();
+ GLCapabilities caps = new GLCapabilities();
+ caps.setDepthBits( 16 );
+ // Create a context that we use to query pixel formats
+ WindowsOnscreenGLContext context = new WindowsOnscreenGLContext( null, caps, null, null );
+ // Start a native thread and grab native screen resources from the thread
+ NativeWindowThread nwt = new NativeWindowThread( rect );
+ nwt.start();
+ long hWnd = 0;
+ long tempHDC = 0;
+ while( (hWnd = nwt.getHWND()) == 0 || (tempHDC = nwt.getHDC()) == 0 ) {
+ Thread.yield();
+ }
+ // Choose a hardware accelerated pixel format
+ PIXELFORMATDESCRIPTOR pfd = context.glCapabilities2PFD( caps, true );
+ int pixelFormat = WGL.ChoosePixelFormat( tempHDC, pfd );
+ if( pixelFormat == 0 ) {
+ System.err.println("Pixel Format is Zero");
+ pendingContextSet.remove(device);
+ return;
+ }
+ // Set the hardware accelerated pixel format
+ if (!WGL.SetPixelFormat(tempHDC, pixelFormat, pfd)) {
+ System.err.println("SetPixelFormat Failed");
+ pendingContextSet.remove( device );
+ return;
+ }
+ // Create a rendering context
+ long tempHGLRC = WGL.wglCreateContext( tempHDC );
+ if( hWnd == 0 || tempHDC == 0 || tempHGLRC == 0 ) {
+ pendingContextSet.remove( device );
+ return;
+ }
+ // Store native handles for later use
+ NativeWindowStruct nws = new NativeWindowStruct();
+ nws.setHWND( hWnd );
+ nws.setWindowsContext( context );
+ nws.setWindowThread( nwt );
+ long currentHDC = WGL.wglGetCurrentDC();
+ long currentHGLRC = WGL.wglGetCurrentContext();
+ // Make the new hardware accelerated context current
+ if( !WGL.wglMakeCurrent( tempHDC, tempHGLRC ) ) {
+ pendingContextSet.remove( device );
+ return;
+ }
+ // Grab function pointers
+ context.hdc = tempHDC;
+ context.hglrc = tempHGLRC;
+ context.resetGLFunctionAvailability();
+ context.createGL();
+ pendingContextSet.remove( device );
+ dummyContextMap.put( device, nws );
+ String availableGLExtensions = "";
+ String availableWGLExtensions = "";
+ String availableEXTExtensions = "";
+ try {
+ availableWGLExtensions = context.getGL().wglGetExtensionsStringARB( currentHDC );
+ } catch( GLException e ) {
+ }
+ try {
+ availableEXTExtensions = context.getGL().wglGetExtensionsStringEXT();
+ } catch( GLException e ) {
+ }
+ availableGLExtensions = context.getGL().glGetString( GL.GL_EXTENSIONS );
+ dummyExtensionsMap.put(device, availableGLExtensions + " " + availableEXTExtensions + " " + availableWGLExtensions);
+ WGL.wglMakeCurrent( currentHDC, currentHGLRC );
+ }
+ }
- public void display(GLDrawable drawable) {
- }
+ /*
+ * This class stores handles to native resources that need to be destroyed
+ * at JVM shutdown.
+ */
+ static class NativeWindowStruct {
+ private long HWND;
+ private WindowsGLContext windowsContext;
+ private Thread windowThread;
+
+ public NativeWindowStruct() {
+ }
- public void reshape(GLDrawable drawable, int x, int y, int width, int height) {
- }
+ public long getHDC() {
+ return( windowsContext.hdc );
+ }
- public void destroy(GLDrawable drawable) {
- }
+ public long getHGLRC() {
+ return( windowsContext.hglrc );
+ }
- public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
- }
- });
- // Attempt to work around deadlock issues with SingleThreadedWorkaround,
- // which causes some of the methods below to block doing work on the AWT thread
+ public void setHWND( long hwnd ) {
+ HWND = hwnd;
+ }
+
+ public long getHWND() {
+ return( HWND );
+ }
+
+ public void setWindowsContext( WindowsGLContext context ) {
+ windowsContext = context;
+ }
+
+ public WindowsGLContext getWindowsContext() {
+ return( windowsContext );
+ }
+
+ public void setWindowThread( Thread thread ) {
+ windowThread = thread;
+ }
+
+ public Thread getWindowThread() {
+ return( windowThread );
+ }
+ }
+
+ /*
+ * Native HWDN and HDC handles must be created and destroyed on the same
+ * thread.
+ */
+
+ static class NativeWindowThread extends Thread {
+ private long HWND = 0;
+ private long HDC = 0;
+ private Rectangle rectangle;
+
+ public NativeWindowThread( Rectangle rect ) {
+ rectangle = rect;
+ }
+
+ public synchronized long getHWND() {
+ return( HWND );
+ }
+
+ public synchronized long getHDC() {
+ return( HDC );
+ }
+
+ public void run() {
+ // Create a native window and device context
+ HWND = WGL.CreateDummyWindow( rectangle.x, rectangle.y, rectangle.width, rectangle.height );
+ HDC = WGL.GetDC( HWND );
+ // Pause this thread until JVM shutdown
try {
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- canvas.setSize(0, 0);
- canvas.setNoAutoRedrawMode(true);
- canvas.setAutoSwapBufferMode(false);
- frame.add(canvas);
- frame.pack();
- frame.show();
- canvas.display();
- }
- });
- } catch (Exception e) {
- throw new GLException(e);
+ synchronized( this ) {
+ wait();
+ }
+ } catch( InterruptedException e ) {
}
+ // Start the message pump at shutdown
+ WGL.NativeEventLoop();
}
+ }
+
+ /*
+ * This class is registered with the JVM to destroy all cached redering
+ * contexts, device contexts, and window handles.
+ */
- return (GL) dummyContextMap.get(device);
+ class ShutdownHook extends Thread {
+ public void run() {
+ // Collect all saved screen resources
+ Collection c = dummyContextMap.values();
+ Iterator iter = c.iterator();
+ while( iter.hasNext() ) {
+ // NativeWindowStruct holds refs to native resources that need to be destroyed
+ NativeWindowStruct struct = (NativeWindowStruct)iter.next();
+ // Restart native window threads to respond to window closing events
+ synchronized( struct.getWindowThread() ) {
+ struct.getWindowThread().notifyAll();
+ }
+ // Destroy OpenGL rendering context
+ if( !WGL.wglDeleteContext( struct.getHGLRC() ) ) {
+ System.err.println( "Error Destroying NativeWindowStruct RC: " + WGL.GetLastError() );
+ }
+ // Send context handles to native method for deletion
+ WGL.DestroyDummyWindow( struct.getHWND(), struct.getHDC() );
+ }
+ }
}
}
diff --git a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
index 5bcdb4559..3bfdee5d1 100644
--- a/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
+++ b/src/net/java/games/jogl/impl/windows/WindowsOnscreenGLContext.java
@@ -136,7 +136,7 @@ public class WindowsOnscreenGLContext extends WindowsGLContext {
}
public synchronized void swapBuffers() throws GLException {
- if (!WGL.SwapBuffers(hdc)) {
+ if (!WGL.SwapBuffers(hdc) && (WGL.GetLastError() != 0)) {
throw new GLException("Error swapping buffers");
}
}