diff --git a/build.xml b/build.xml index d8158a98..ed7f7c81 100644 --- a/build.xml +++ b/build.xml @@ -559,6 +559,11 @@ + + + + + @@ -569,6 +574,7 @@ + @@ -577,7 +583,6 @@ - diff --git a/src/java/org/lwjgl/examples/spaceinvaders/Game.java b/src/java/org/lwjgl/examples/spaceinvaders/Game.java index 74210c42..dd672ab4 100644 --- a/src/java/org/lwjgl/examples/spaceinvaders/Game.java +++ b/src/java/org/lwjgl/examples/spaceinvaders/Game.java @@ -272,10 +272,10 @@ public class Game { * Sets the display mode for fullscreen mode */ private boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(width, height, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(width, height, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + width, "height=" + height, diff --git a/src/java/org/lwjgl/input/Cursor.java b/src/java/org/lwjgl/input/Cursor.java index 201d3272..1e627559 100644 --- a/src/java/org/lwjgl/input/Cursor.java +++ b/src/java/org/lwjgl/input/Cursor.java @@ -64,6 +64,8 @@ public class Cursor { /** Index into list of cursors */ private int index = 0; + + private boolean destroyed; /** * Constructs a new Cursor, with the given parameters. Mouse must have been created before you can create @@ -219,15 +221,23 @@ public class Cursor { * Gets the native handle associated with the cursor object. */ Object getHandle() { + checkValid(); return cursors[index].cursorHandle; } + private void checkValid() { + if (destroyed) + throw new IllegalStateException("The cursor is destroyed"); + } + /** * Destroy the native cursor. If the cursor is current, * the current native cursor is set to null (the default * OS cursor) */ public void destroy() { + if (destroyed) + return; if (Mouse.getNativeCursor() == this) { try { Mouse.setNativeCursor(null); @@ -238,12 +248,14 @@ public class Cursor { for(int i=0; i 1 && cursors[index].timeout < System.currentTimeMillis(); } @@ -259,6 +272,7 @@ public class Cursor { * Changes to the next cursor */ protected void nextCursor() { + checkValid(); index = ++index % cursors.length; } diff --git a/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java new file mode 100644 index 00000000..555ca38f --- /dev/null +++ b/src/java/org/lwjgl/opengl/AWTCanvasImplementation.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; + +import java.awt.GraphicsDevice; +import java.awt.GraphicsConfiguration; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +interface AWTCanvasImplementation { + /** + * Return an opaque handle to the canvas peer information required to create a context from it. + */ + public PeerInfo createPeerInfo(AWTGLCanvas canvas) throws LWJGLException; + + /** + * Find a proper GraphicsConfiguration from the given GraphicsDevice and PixelFormat. + * + * @return A GraphicsConfiguration matching the given GraphicsConfiguration and PixelFormat. + * @throws LWJGLException if no suitable configuration could be found. + */ + public GraphicsConfiguration findConfiguration(GraphicsDevice device, PixelFormat pixel_format) throws LWJGLException; +} diff --git a/src/java/org/lwjgl/opengl/AWTGLCanvas.java b/src/java/org/lwjgl/opengl/AWTGLCanvas.java index b07a02d2..1e5560b1 100644 --- a/src/java/org/lwjgl/opengl/AWTGLCanvas.java +++ b/src/java/org/lwjgl/opengl/AWTGLCanvas.java @@ -33,6 +33,8 @@ package org.lwjgl.opengl; import java.awt.Canvas; import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import org.lwjgl.LWJGLException; import org.lwjgl.Sys; @@ -45,37 +47,88 @@ import org.lwjgl.Sys; * @version $Revision$ * @author $Author$ */ -public class AWTGLCanvas extends Canvas { +public class AWTGLCanvas extends Canvas implements Drawable { + private final static AWTCanvasImplementation implementation; static { System.loadLibrary("jawt"); Sys.initialize(); + String class_name; + String OS_NAME = System.getProperty("os.name"); + if (OS_NAME.startsWith("Linux")) { + class_name = "org.lwjgl.opengl.LinuxCanvasImplementation"; + } else if (OS_NAME.startsWith("Windows")) { + class_name = "org.lwjgl.opengl.DefaultCanvasImplementation"; + } else if (OS_NAME.startsWith("Mac")) { + class_name = "org.lwjgl.opengl.DefaultCanvasImplementation"; + } else + throw new IllegalStateException("The platform " + OS_NAME + " is not supported"); + try { + Class impl_class = Class.forName(class_name); + implementation = (AWTCanvasImplementation)impl_class.newInstance(); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } } /** The requested pixel format */ - private PixelFormat pixelFormat; + private final PeerInfo peer_info; + + /** The drawable to share context with */ + private final Drawable drawable; /** Context handle */ - private long context; + private Context context; + + /** + * This method should only be called internally. + */ + public Context getContext() { + return context; + } /** * Constructor using the default PixelFormat. */ - public AWTGLCanvas() { + public AWTGLCanvas() throws LWJGLException { this(new PixelFormat()); } /** - * Create an AWTGLCanvas with the requested PixelFormat. Construction is always - * successful, however, when the time comes to actually realise the component on the - * screen + * Create an AWTGLCanvas with the requested PixelFormat on the default GraphicsDevice. + * * @param pixelFormat The desired pixel format. May not be null + * @param device the device to create the canvas on. */ - public AWTGLCanvas(PixelFormat pixelFormat) { - if (pixelFormat == null) { - throw new IllegalArgumentException("Pixel format may not be null"); - } - this.pixelFormat = pixelFormat; + public AWTGLCanvas(PixelFormat pixel_format) throws LWJGLException { + this(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(), pixel_format); + } + + /** + * Create an AWTGLCanvas with the requested PixelFormat on the default GraphicsDevice. + * + * @param pixelFormat The desired pixel format. May not be null + * @param device the device to create the canvas on. + */ + public AWTGLCanvas(GraphicsDevice device, PixelFormat pixel_format) throws LWJGLException { + this(device, pixel_format, null); + } + + /** + * Create an AWTGLCanvas with the requested PixelFormat on the specified GraphicsDevice. + * + * @param device the device to create the canvas on. + * @param pixelFormat The desired pixel format. May not be null + * @param shared_drawable The Drawable to share context with + */ + public AWTGLCanvas(GraphicsDevice device, PixelFormat pixel_format, Drawable drawable) throws LWJGLException { + super(implementation.findConfiguration(device, pixel_format)); + this.peer_info = implementation.createPeerInfo(this); + this.drawable = drawable; } /* (non-Javadoc) @@ -94,64 +147,74 @@ public class AWTGLCanvas extends Canvas { * @see java.awt.Component#removeNotify() */ public void removeNotify() { - super.removeNotify(); try { destroyContext(); } catch (LWJGLException e) { throw new RuntimeException(e); } + super.removeNotify(); } + /** + * Enable vsync + */ + public synchronized void setVSyncEnabled(boolean enabled) throws LWJGLException { + if (context == null) + throw new IllegalStateException("Canvas not yet displayable"); + context.setVSync(enabled); + } + + /** + * Swap the canvas' buffer + */ + public synchronized void swapBuffers() throws LWJGLException { + if (context == null) + throw new IllegalStateException("Canvas not yet displayable"); + context.swapBuffers(); + } + + public synchronized void releaseContext() throws LWJGLException { + if (context == null) + throw new IllegalStateException("Canvas not yet displayable"); + if (context.isCurrent()) + Context.releaseCurrentContext(); + } + + /** + * Make the canvas' context current. It is highly recommended that the context + * is only made current inside the AWT thread (for example in an overridden paint()). + */ + public synchronized void makeCurrent() throws LWJGLException { + if (context == null) + throw new IllegalStateException("Canvas not yet displayable"); + context.makeCurrent(); + } + /** * Create the OpenGL context. This occurs when the component becomes displayable * @throws LWJGLException */ private synchronized void createContext() throws LWJGLException { - nCreateContext(); + if (context == null) + context = new Context(peer_info, drawable != null ? drawable.getContext() : null); } - private native void nCreateContext() throws LWJGLException; /** - * Destroy the OpenGL context. This occurs when the component is no longer displayable. + * Destroy the OpenGL context. This happens when the component becomes undisplayable */ private synchronized void destroyContext() throws LWJGLException { - nDestroyContext(); + context.forceDestroy(); + context = null; } - private native void nDestroyContext() throws LWJGLException; - - /* (non-Javadoc) - * @see java.awt.Canvas#paint(java.awt.Graphics) - */ - public synchronized final void paint(Graphics g) { - try { - nPaint(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - private native void nPaint() throws Exception; - /** - * Paint callback from native code + * Empty paint to avoid clearing */ - private final void cPaint() { - try { - GLContext.useContext(this); - } catch (LWJGLException e) { - throw new RuntimeException(e); - } - doPaint(); + public void paint(Graphics g) { } - + /** - * Do painting. Override this method to call GL commands. - */ - protected void doPaint() { - } - - /* (non-Javadoc) - * @see java.awt.Canvas#update(java.awt.Graphics) + * override update to avoid clearing */ public void update(Graphics g) { paint(g); diff --git a/src/java/org/lwjgl/opengl/AWTSurfaceLock.java b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java new file mode 100644 index 00000000..9b3812c2 --- /dev/null +++ b/src/java/org/lwjgl/opengl/AWTSurfaceLock.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +import java.awt.Canvas; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +final class AWTSurfaceLock { + private final static int LOCK_HANDLE_SIZE = 64; + private final ByteBuffer lock_buffer = BufferUtils.createByteBuffer(LOCK_HANDLE_SIZE); + + public ByteBuffer lockAndGetHandle(Canvas canvas) throws LWJGLException { + lockAndInitHandle(lock_buffer, canvas); + return lock_buffer; + } + private static native void lockAndInitHandle(ByteBuffer lock_buffer, Canvas canvas) throws LWJGLException; + + protected void unlock() throws LWJGLException { + nUnlock(lock_buffer); + } + private static native void nUnlock(ByteBuffer lock_buffer) throws LWJGLException; +} diff --git a/src/java/org/lwjgl/opengl/Context.java b/src/java/org/lwjgl/opengl/Context.java new file mode 100644 index 00000000..d3d8f70a --- /dev/null +++ b/src/java/org/lwjgl/opengl/Context.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +/** + * $Id$ + *

+ * Context encapsulates an OpenGL context. + *

+ * + * This class is thread-safe. + * + * @author elias_naur + * @version $Revision$ + */ +final class Context { + /** + * The platform specific implementation of context methods + */ + private final static ContextImplementation implementation; + + /** The current Context */ + private final static ThreadLocal current_context_local = new ThreadLocal(); + + /** + * Handle to the native GL rendering context + */ + private final ByteBuffer handle; + private final PeerInfo peer_info; + + /** Whether the context has been destroyed */ + private boolean destroyed; + + private boolean destroy_requested; + + /** The thread that has this context current, or null. */ + private Thread thread; + + static { + Sys.initialize(); + String class_name; + String OS_NAME = System.getProperty("os.name"); + if (OS_NAME.startsWith("Linux")) { + class_name = "org.lwjgl.opengl.LinuxContextImplementation"; + } else if (OS_NAME.startsWith("Windows")) { + class_name = "org.lwjgl.opengl.Win32ContextImplementation"; + } else if (OS_NAME.startsWith("Mac")) { + class_name = "org.lwjgl.opengl.MacOSXContextImplementation"; + } else + throw new IllegalStateException("The platform " + OS_NAME + " is not supported"); + try { + Class impl_class = Class.forName(class_name); + implementation = (ContextImplementation)impl_class.newInstance(); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } + } + + PeerInfo getPeerInfo() { + return peer_info; + } + + static Context getCurrentContext() { + return (Context)current_context_local.get(); + } + + /** + * Create a context with the specified peer info and shared context + */ + public Context(PeerInfo peer_info, Context shared_context) throws LWJGLException { + Context context_lock = shared_context != null ? shared_context : this; + // If shared_context is not null, synchronize on it to make sure it is not deleted + // while this context is created. Otherwise, simply synchronize on ourself to avoid NPE + synchronized (context_lock) { + if (shared_context != null && shared_context.destroyed) + throw new IllegalArgumentException("Shared context is destroyed"); + GLContext.loadOpenGLLibrary(); + try { + this.peer_info = peer_info; + this.handle = implementation.create(peer_info, shared_context != null ? shared_context.handle : null); + } catch (LWJGLException e) { + GLContext.unloadOpenGLLibrary(); + throw e; + } + } + } + + /** + * Release the current context (if any). After this call, no context is current. + */ + public static void releaseCurrentContext() throws LWJGLException { + Context current_context = getCurrentContext(); + if (current_context != null) { + implementation.releaseCurrentContext(); + GLContext.useContext(null); + current_context_local.set(null); + synchronized (current_context) { + current_context.thread = null; + current_context.checkDestroy(); + } + } + } + + /** + * Swap the buffers on the current context. Only valid for double-buffered contexts + */ + public static void swapBuffers() throws LWJGLException { + implementation.swapBuffers(); + } + + private boolean canAccess() { + return thread == null || Thread.currentThread() == thread; + } + + private void checkAccess() { + if (!canAccess()) + throw new IllegalStateException("From thread " + Thread.currentThread() + ": " +thread + " already has the context current"); + } + + /** + * Make the context current + */ + public synchronized void makeCurrent() throws LWJGLException { + checkAccess(); + if (destroyed) + throw new IllegalStateException("Context is destroyed"); + thread = Thread.currentThread(); + current_context_local.set(this); + implementation.makeCurrent(peer_info, handle); + GLContext.useContext(this); + } + + /** + * Query whether the context is current + */ + public synchronized boolean isCurrent() throws LWJGLException { + if (destroyed) + throw new IllegalStateException("Context is destroyed"); + return implementation.isCurrent(handle); + } + + private void checkDestroy() { + if (!destroyed && destroy_requested) { + try { + implementation.destroy(peer_info, handle); + destroyed = true; + thread = null; + GLContext.unloadOpenGLLibrary(); + } catch (LWJGLException e) { + Sys.log("Exception occurred while destroying context: " + e); + } + } + } + + /** + * Enable or disable vertical monitor synchronization. This call is a best-attempt at changing + * the monitor vertical refresh synchronization of the context, and is not guaranteed to be successful. + * @param sync true to synchronize; false to ignore synchronization + */ + public synchronized void setVSync(boolean enable) { + implementation.setVSync(enable); + } + + /** + * Destroy the context. This method behaves the same as destroy() with the extra + * requirement that the context must be either current to the current thread or not + * current at all. + */ + public synchronized void forceDestroy() throws LWJGLException { + checkAccess(); + destroy(); + } + + /** + * Request destruction of the Context. If the context is current, no context will be current after this call. + * The context is destroyed when no thread has it current. + */ + public synchronized void destroy() throws LWJGLException { + if (destroyed) + return; + destroy_requested = true; + boolean was_current = isCurrent(); + int error = GL11.GL_NO_ERROR; + if (was_current) { + error = GL11.glGetError(); + releaseCurrentContext(); + } + checkDestroy(); + if (was_current && error != GL11.GL_NO_ERROR) + throw new OpenGLException(error); + } +} diff --git a/src/java/org/lwjgl/opengl/ContextImplementation.java b/src/java/org/lwjgl/opengl/ContextImplementation.java new file mode 100644 index 00000000..3d4424b4 --- /dev/null +++ b/src/java/org/lwjgl/opengl/ContextImplementation.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; + +/** + * $Id$ + *

+ * Context implementation interface. + *

+ * + * @author elias_naur + * @version $Revision$ + */ +interface ContextImplementation { + /** + * Create a context. + */ + public ByteBuffer create(PeerInfo peer_info, ByteBuffer shared_context_handle) throws LWJGLException; + + /** + * Swap the buffers of the current context. Only valid for double-buffered contexts. + */ + public void swapBuffers() throws LWJGLException; + + /** + * Release the current context (if any). After this call, no context is current. + */ + public void releaseCurrentContext() throws LWJGLException; + + /** + * Query whether the context is current + */ + public void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException; + + /** + * Query whether the context is current + */ + public boolean isCurrent(ByteBuffer handle) throws LWJGLException; + + public void setVSync(boolean enable); + + /** + * Destroys the Context. + */ + public void destroy(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException; +} diff --git a/src/java/org/lwjgl/opengl/Display.java b/src/java/org/lwjgl/opengl/Display.java index fe46bb9a..80e7ac06 100644 --- a/src/java/org/lwjgl/opengl/Display.java +++ b/src/java/org/lwjgl/opengl/Display.java @@ -86,20 +86,41 @@ public final class Display { private static boolean vsync; /** A unique context object, so we can track different contexts between creates() and destroys() */ - private static Display context; + private static Context context; private static boolean window_created = false; static { Sys.initialize(); display_impl = createDisplayImplementation(); - current_mode = initial_mode = display_impl.init(); - Sys.log("Initial mode: " + initial_mode); - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - reset(); - } - }); + try { + current_mode = initial_mode = display_impl.init(); + Sys.log("Initial mode: " + initial_mode); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + reset(); + } + }); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } + } + + /** + * Fetch the Drawable from the Display. + * + * @return the Drawable corresponding to the Display context, or null it display is + * not created. + */ + public static Drawable getDrawable() { + if (context != null) { + return new Drawable() { + public Context getContext() { + return context; + } + }; + } else + return null; } private static DisplayImplementation createDisplayImplementation() { @@ -141,7 +162,7 @@ public final class Display { * * @return an array of all display modes the system reckons it can handle. */ - public static DisplayMode[] getAvailableDisplayModes() { + public static DisplayMode[] getAvailableDisplayModes() throws LWJGLException { DisplayMode[] unfilteredModes = display_impl.getAvailableDisplayModes(); if (unfilteredModes == null) { @@ -192,7 +213,7 @@ public final class Display { switchDisplayMode(); createWindow(); } catch (LWJGLException e) { - display_impl.destroyContext(); + destroyContext(); display_impl.resetDisplayMode(); throw e; } @@ -385,7 +406,7 @@ public final class Display { } createWindow(); } catch (LWJGLException e) { - display_impl.destroyContext(); + destroyContext(); display_impl.resetDisplayMode(); throw e; } @@ -483,7 +504,11 @@ public final class Display { // We paint only when the window is visible or dirty if (isVisible() || isDirty()) { Util.checkGLError(); - display_impl.swapBuffers(); + try { + context.swapBuffers(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } } processMessages(); @@ -505,8 +530,7 @@ public final class Display { public static void makeCurrent() throws LWJGLException { if (!isCreated()) throw new IllegalStateException("No window created to make current"); - display_impl.makeCurrent(); - GLContext.useContext(context); + context.makeCurrent(); } /** @@ -537,25 +561,35 @@ public final class Display { * @throws LWJGLException */ public static void create(PixelFormat pixel_format) throws LWJGLException { + create(pixel_format, null); + } + + /** + * Create the OpenGL context with the given minimum parameters. If isFullscreen() is true or if windowed + * context are not supported on the platform, the display mode will be switched to the mode returned by + * getDisplayMode(), and a fullscreen context will be created. If isFullscreen() is false, a windowed context + * will be created with the dimensions given in the mode returned by getDisplayMode(). If a context can't be + * created with the given parameters, a LWJGLException will be thrown. + * + *

The window created will be set up in orthographic 2D projection, with 1:1 pixel ratio with GL coordinates. + * + * @param pixel_format Describes the minimum specifications the context must fulfill. + * @param shared_drawable The Drawable to share context with. + * @throws LWJGLException + */ + public static void create(PixelFormat pixel_format, Drawable shared_drawable) throws LWJGLException { if (isCreated()) throw new IllegalStateException("Only one LWJGL context may be instantiated at any one time."); if (fullscreen) switchDisplayMode(); try { - GLContext.loadOpenGLLibrary(); + PeerInfo peer_info = display_impl.createPeerInfo(pixel_format); + context = new Context(peer_info, shared_drawable != null ? shared_drawable.getContext() : null); try { - display_impl.createContext(pixel_format); - try { - context = new Display(); - createWindow(); - initContext(); - } catch (LWJGLException e) { - display_impl.destroyContext(); - context = null; - throw e; - } + createWindow(); + initContext(); } catch (LWJGLException e) { - GLContext.unloadOpenGLLibrary(); + destroyContext(); throw e; } } catch (LWJGLException e) { @@ -617,18 +651,22 @@ public final class Display { } destroyWindow(); - display_impl.destroyContext(); - GLContext.unloadOpenGLLibrary(); - context = null; - x = y = -1; - try { - GLContext.useContext(null); - } catch (LWJGLException e) { - Sys.log("Failed to reset GLContext due to: " + e); - } + destroyContext(); + x = y = -1; reset(); } + private static void destroyContext() { + try { + context.forceDestroy(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } finally { + context = null; + display_impl.destroyPeerInfo(); + } + } + /* * Reset display mode if fullscreen. This method is also called from the shutdown hook added * in the static constructor @@ -641,7 +679,7 @@ public final class Display { /** * @return the unique Display context (or null, if the Display has not been created) */ - public static Object getContext() { + public static Context getContext() { return context; } @@ -660,7 +698,7 @@ public final class Display { public static void setVSyncEnabled(boolean sync) { vsync = sync; if (isCreated()) - display_impl.setVSyncEnabled(vsync); + context.setVSync(vsync); } /** diff --git a/src/java/org/lwjgl/opengl/DisplayImplementation.java b/src/java/org/lwjgl/opengl/DisplayImplementation.java index f9077d18..f4513768 100644 --- a/src/java/org/lwjgl/opengl/DisplayImplementation.java +++ b/src/java/org/lwjgl/opengl/DisplayImplementation.java @@ -87,7 +87,7 @@ public interface DisplayImplementation { /** * Initialize and return the current display mode. */ - DisplayMode init(); + DisplayMode init() throws LWJGLException; /** * Implementation of setTitle(). This will read the window's title member @@ -103,22 +103,12 @@ public interface DisplayImplementation { boolean isDirty(); /** - * Swap double buffers. - */ - void swapBuffers(); - - /** - * Make the window the current rendering context for GL calls. - */ - void makeCurrent() throws LWJGLException; - - /** - * Create the native OpenGL context. + * Create the native PeerInfo. * @throws LWJGLException */ - void createContext(PixelFormat pixel_format) throws LWJGLException; + PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException; - void destroyContext(); + void destroyPeerInfo(); /** * Updates the windows internal state. This must be called at least once per video frame @@ -126,14 +116,12 @@ public interface DisplayImplementation { */ void update(); - void setVSyncEnabled(boolean sync); - void reshape(int x, int y, int width, int height); /** * Method for getting displaymodes */ - DisplayMode[] getAvailableDisplayModes(); + DisplayMode[] getAvailableDisplayModes() throws LWJGLException; /* * Mouse methods @@ -147,7 +135,7 @@ public interface DisplayImplementation { /** * Method to create the mouse. */ - void createMouse(); + void createMouse() throws LWJGLException; /** * Method the destroy the mouse @@ -224,28 +212,23 @@ public interface DisplayImplementation { /** * Method to test for buffer integrity */ - public boolean isBufferLost(ByteBuffer handle); - - /** - * Method to make a pbuffer current. - */ - public void makePbufferCurrent(ByteBuffer handle) throws LWJGLException; + public boolean isBufferLost(PeerInfo handle); /** * Method to create a Pbuffer */ - public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, + public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, - IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException; + IntBuffer pBufferAttribs) throws LWJGLException; /** * Destroy pbuffer */ - public void destroyPbuffer(ByteBuffer handle); + public void destroyPbuffer(PeerInfo handle); - public void setPbufferAttrib(ByteBuffer handle, int attrib, int value); + public void setPbufferAttrib(PeerInfo handle, int attrib, int value); - public void bindTexImageToPbuffer(ByteBuffer handle, int buffer); + public void bindTexImageToPbuffer(PeerInfo handle, int buffer); - public void releaseTexImageFromPbuffer(ByteBuffer handle, int buffer); + public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer); } diff --git a/src/java/org/lwjgl/opengl/Drawable.java b/src/java/org/lwjgl/opengl/Drawable.java new file mode 100644 index 00000000..a5a6dcf6 --- /dev/null +++ b/src/java/org/lwjgl/opengl/Drawable.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +/** + * The Drawable interface describes an OpenGL drawable with an associated + * Context. + * + * @author elias_naur + */ + +public interface Drawable { + Context getContext(); +} diff --git a/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java new file mode 100644 index 00000000..9cb5b193 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxAWTGLCanvasPeerInfo.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +final class LinuxAWTGLCanvasPeerInfo extends LinuxPeerInfo { + private final static int LOCK_HANDLE_SIZE = 64; + private final ByteBuffer lock_buffer = BufferUtils.createByteBuffer(LOCK_HANDLE_SIZE); + private final AWTGLCanvas canvas; + private final AWTSurfaceLock awt_surface = new AWTSurfaceLock(); + + public LinuxAWTGLCanvasPeerInfo(AWTGLCanvas canvas) { + this.canvas = canvas; + } + + protected void doLockAndInitHandle() throws LWJGLException { + int screen = LinuxCanvasImplementation.getScreenFromDevice(canvas.getGraphicsConfiguration().getDevice()); + nInitHandle(screen, awt_surface.lockAndGetHandle(canvas), getHandle()); + } + private static native void nInitHandle(int screen, ByteBuffer surface_buffer, ByteBuffer peer_info_handle) throws LWJGLException; + + protected void doUnlock() throws LWJGLException { + awt_surface.unlock(); + } +} diff --git a/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java new file mode 100644 index 00000000..78f3a5c2 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxCanvasImplementation.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.BufferUtils; + +import java.awt.GraphicsDevice; +import java.awt.GraphicsConfiguration; + +/* + * Import the needed SUN specific classes. They + * are needed since there is no official way to access + * the screen and visual from GraphicsDevice and + * GraphicsConfiguration respectively. + */ +import sun.awt.X11GraphicsDevice; +import sun.awt.X11GraphicsConfig; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +final class LinuxCanvasImplementation implements AWTCanvasImplementation { + static int getScreenFromDevice(GraphicsDevice device) { + X11GraphicsDevice x11_device = (X11GraphicsDevice)device; + return x11_device.getScreen(); + } + + private static int getVisualIDFromConfiguration(GraphicsConfiguration configuration) { + X11GraphicsConfig x11_config = (X11GraphicsConfig)configuration; + return x11_config.getVisual(); + } + + public PeerInfo createPeerInfo(AWTGLCanvas canvas) throws LWJGLException { + return new LinuxAWTGLCanvasPeerInfo(canvas); + } + + /** + * Find a proper GraphicsConfiguration from the given GraphicsDevice and PixelFormat. + * + * @return The GraphicsConfiguration corresponding to a visual that matches the pixel format. + */ + public GraphicsConfiguration findConfiguration(GraphicsDevice device, PixelFormat pixel_format) throws LWJGLException { + X11GraphicsDevice x11_device = (X11GraphicsDevice)device; + int screen = getScreenFromDevice(device); + int visual_id_matching_format = findVisualIDFromFormat(screen, pixel_format); + GraphicsConfiguration[] configurations = device.getConfigurations(); + for (int i = 0; i < configurations.length; i++) { + int visual_id = getVisualIDFromConfiguration(configurations[i]); + if (visual_id == visual_id_matching_format) + return configurations[i]; + } + throw new LWJGLException("Could not find the matching GraphicsConfiguration to visual id"); + } + + private static int findVisualIDFromFormat(int screen, PixelFormat pixel_format) throws LWJGLException { + try { + LinuxDisplay.lockAWT(); + try { + GLContext.loadOpenGLLibrary(); + try { + LinuxDisplay.incDisplay(); + return nFindVisualIDFromFormat(screen, pixel_format); + } finally { + LinuxDisplay.decDisplay(); + } + } finally { + GLContext.unloadOpenGLLibrary(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native int nFindVisualIDFromFormat(int screen, PixelFormat pixel_format) throws LWJGLException; +} diff --git a/src/java/org/lwjgl/opengl/LinuxContextImplementation.java b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java new file mode 100644 index 00000000..613ad687 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxContextImplementation.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.BufferUtils; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +final class LinuxContextImplementation implements ContextImplementation { + private final static int HANDLE_SIZE = 64; + + private static PeerInfo getCurrentPeerInfo() { + return Context.getCurrentContext().getPeerInfo(); + } + + public ByteBuffer create(PeerInfo peer_info, ByteBuffer shared_context_handle) throws LWJGLException { + ByteBuffer handle = BufferUtils.createByteBuffer(HANDLE_SIZE); + LinuxDisplay.lockAWT(); + try { + ByteBuffer peer_handle = peer_info.lockAndGetHandle(); + try { + nCreate(peer_handle, handle, shared_context_handle); + return handle; + } finally { + peer_info.unlock(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + + private static native void nCreate(ByteBuffer peer_handle, ByteBuffer context_handle, ByteBuffer shared_context_handle) throws LWJGLException; + + public void swapBuffers() throws LWJGLException { + PeerInfo current_peer_info = getCurrentPeerInfo(); + if (current_peer_info == null) + throw new IllegalStateException("No context is current"); + LinuxDisplay.lockAWT(); + try { + ByteBuffer peer_handle = current_peer_info.lockAndGetHandle(); + try { + nSwapBuffers(peer_handle); + } finally { + current_peer_info.unlock(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native void nSwapBuffers(ByteBuffer peer_info_handle) throws LWJGLException; + + public void releaseCurrentContext() throws LWJGLException { + PeerInfo current_peer_info = getCurrentPeerInfo(); + if (current_peer_info == null) + return; // No context is current + LinuxDisplay.lockAWT(); + try { + ByteBuffer peer_handle = current_peer_info.lockAndGetHandle(); + try { + nReleaseCurrentContext(peer_handle); + } finally { + current_peer_info.unlock(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native void nReleaseCurrentContext(ByteBuffer peer_info_handle) throws LWJGLException; + + public void makeCurrent(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException { + LinuxDisplay.lockAWT(); + try { + ByteBuffer peer_handle = peer_info.lockAndGetHandle(); + try { + nMakeCurrent(peer_handle, handle); + } finally { + peer_info.unlock(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native void nMakeCurrent(ByteBuffer peer_handle, ByteBuffer context_handle) throws LWJGLException; + + public boolean isCurrent(ByteBuffer handle) throws LWJGLException { + LinuxDisplay.lockAWT(); + try { + boolean result = nIsCurrent(handle); + return result; + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native boolean nIsCurrent(ByteBuffer context_handle) throws LWJGLException; + + public void setVSync(boolean enabled) { + LinuxDisplay.lockAWT(); + nSetVSync(enabled); + LinuxDisplay.unlockAWT(); + } + private static native void nSetVSync(boolean enabled); + + public void destroy(PeerInfo peer_info, ByteBuffer handle) throws LWJGLException { + LinuxDisplay.lockAWT(); + try { + ByteBuffer peer_handle = peer_info.lockAndGetHandle(); + try { + nDestroy(peer_handle, handle); + } finally { + peer_info.unlock(); + } + } finally { + LinuxDisplay.unlockAWT(); + } + } + private static native void nDestroy(ByteBuffer peer_handle, ByteBuffer context_handle) throws LWJGLException; +} diff --git a/src/java/org/lwjgl/opengl/LinuxDisplay.java b/src/java/org/lwjgl/opengl/LinuxDisplay.java index 31764ff0..302c5780 100644 --- a/src/java/org/lwjgl/opengl/LinuxDisplay.java +++ b/src/java/org/lwjgl/opengl/LinuxDisplay.java @@ -42,6 +42,7 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; +import org.lwjgl.Sys; import org.lwjgl.BufferUtils; import org.lwjgl.LWJGLException; import org.lwjgl.input.Keyboard; @@ -51,41 +52,62 @@ final class LinuxDisplay implements DisplayImplementation { private static final int PBUFFER_HANDLE_SIZE = 24; private static final int NUM_BUTTONS = 3; + private static PeerInfo peer_info; + /* Since Xlib is not guaranteed to be thread safe, we need a way to synchronize LWJGL - * Xlib calls with AWT Xlib calls. Fortunately, JAWT implements LockAWT and UnlockAWT(), to + * Xlib calls with AWT Xlib calls. Fortunately, JAWT implements LockAWT and UnlockAWT() to * do just that. */ - private native void lockAWT(); - private native void unlockAWT(); - + static native void lockAWT(); + static native void unlockAWT(); + + /** + * increment and decrement display usage. + */ + static native void incDisplay() throws LWJGLException; + static native void decDisplay(); + public void createWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException { lockAWT(); - nCreateWindow(mode, fullscreen, x, y); - unlockAWT(); + try { + ByteBuffer handle = peer_info.lockAndGetHandle(); + try { + nCreateWindow(handle, mode, fullscreen, x, y); + } finally { + peer_info.unlock(); + } + } finally { + unlockAWT(); + } } - public native void nCreateWindow(DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException; - + private static native void nCreateWindow(ByteBuffer peer_info_handle, DisplayMode mode, boolean fullscreen, int x, int y) throws LWJGLException; public void destroyWindow() { lockAWT(); nDestroyWindow(); unlockAWT(); } - public native void nDestroyWindow(); + private static native void nDestroyWindow(); public void switchDisplayMode(DisplayMode mode) throws LWJGLException { lockAWT(); - nSwitchDisplayMode(mode); - unlockAWT(); + try { + nSwitchDisplayMode(mode); + } finally { + unlockAWT(); + } } - public native void nSwitchDisplayMode(DisplayMode mode) throws LWJGLException; - + private static native void nSwitchDisplayMode(DisplayMode mode) throws LWJGLException; + public void resetDisplayMode() { lockAWT(); - nResetDisplayMode(); - unlockAWT(); + try { + nResetDisplayMode(); + } finally { + unlockAWT(); + } } - public native void nResetDisplayMode(); + private static native void nResetDisplayMode(); public int getGammaRampLength() { lockAWT(); @@ -93,126 +115,130 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return length; } - public native int nGetGammaRampLength(); - + private static native int nGetGammaRampLength(); + public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException { lockAWT(); - nSetGammaRamp(gammaRamp); - unlockAWT(); + try { + nSetGammaRamp(gammaRamp); + } finally { + unlockAWT(); + } } - public native void nSetGammaRamp(FloatBuffer gammaRamp) throws LWJGLException; + private static native void nSetGammaRamp(FloatBuffer gammaRamp) throws LWJGLException; public String getAdapter() { return null; } - + public String getVersion() { return null; } - - public DisplayMode init() { + + public DisplayMode init() throws LWJGLException { lockAWT(); - DisplayMode mode = nInit(); - unlockAWT(); - return mode; + try { + DisplayMode mode = nInit(); + return mode; + } finally { + unlockAWT(); + } } - public native DisplayMode nInit(); + private static native DisplayMode nInit() throws LWJGLException; public void setTitle(String title) { lockAWT(); nSetTitle(title); unlockAWT(); } - public native void nSetTitle(String title); - + private static native void nSetTitle(String title); + public boolean isCloseRequested() { lockAWT(); boolean result = nIsCloseRequested(); unlockAWT(); return result; } - public native boolean nIsCloseRequested(); - + private static native boolean nIsCloseRequested(); + public boolean isVisible() { lockAWT(); boolean result = nIsVisible(); unlockAWT(); return result; } - public native boolean nIsVisible(); - + private static native boolean nIsVisible(); + public boolean isActive() { lockAWT(); boolean result = nIsActive(); unlockAWT(); return result; } - public native boolean nIsActive(); - + private static native boolean nIsActive(); + public boolean isDirty() { lockAWT(); boolean result = nIsDirty(); unlockAWT(); return result; } - public native boolean nIsDirty(); - - public void swapBuffers() { - lockAWT(); - nSwapBuffers(); - unlockAWT(); - } - public native void nSwapBuffers(); + private static native boolean nIsDirty(); - public void makeCurrent() throws LWJGLException { + public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException { lockAWT(); - nMakeCurrent(); - unlockAWT(); + try { + incDisplay(); + try { + GLContext.loadOpenGLLibrary(); + try { + peer_info = new LinuxDisplayPeerInfo(pixel_format); + return peer_info; + } catch (LWJGLException e) { + GLContext.unloadOpenGLLibrary(); + throw e; + } + } catch (LWJGLException e) { + decDisplay(); + throw e; + } + } finally { + unlockAWT(); + } } - public native void nMakeCurrent() throws LWJGLException; - - public void createContext(PixelFormat pixel_format) throws LWJGLException { - lockAWT(); - nCreateContext(pixel_format); - unlockAWT(); - } - public native void nCreateContext(PixelFormat pixel_format) throws LWJGLException; - public void destroyContext() { + public void destroyPeerInfo() { lockAWT(); - nDestroyContext(); + peer_info = null; + GLContext.unloadOpenGLLibrary(); + decDisplay(); unlockAWT(); } - public native void nDestroyContext(); public void update() { lockAWT(); nUpdate(); unlockAWT(); } - public native void nUpdate(); - - public void setVSyncEnabled(boolean sync) { - lockAWT(); - nSetVSyncEnabled(sync); - unlockAWT(); - } - public native void nSetVSyncEnabled(boolean sync); + private static native void nUpdate(); public void reshape(int x, int y, int width, int height) { lockAWT(); nReshape(x, y, width, height); unlockAWT(); } - public native void nReshape(int x, int y, int width, int height); + private static native void nReshape(int x, int y, int width, int height); - public DisplayMode[] getAvailableDisplayModes() { + public DisplayMode[] getAvailableDisplayModes() throws LWJGLException { lockAWT(); - DisplayMode[] modes = nGetAvailableDisplayModes(); - unlockAWT(); - return modes; + try { + DisplayMode[] modes = nGetAvailableDisplayModes(); + return modes; + } finally { + unlockAWT(); + } } - public native DisplayMode[] nGetAvailableDisplayModes(); + private static native DisplayMode[] nGetAvailableDisplayModes() throws LWJGLException; /* Mouse */ public boolean hasWheel() { @@ -228,20 +254,20 @@ final class LinuxDisplay implements DisplayImplementation { nCreateMouse(); unlockAWT(); } - public native void nCreateMouse(); + private static native void nCreateMouse(); public void destroyMouse() { lockAWT(); nDestroyMouse(); unlockAWT(); } - public native void nDestroyMouse(); + private static native void nDestroyMouse(); public void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons) { lockAWT(); nPollMouse(coord_buffer, buttons); unlockAWT(); } - public native void nPollMouse(IntBuffer coord_buffer, ByteBuffer buttons); + private static native void nPollMouse(IntBuffer coord_buffer, ByteBuffer buttons); public int readMouse(IntBuffer buffer, int buffer_position) { lockAWT(); @@ -249,29 +275,36 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return count; } - public native int nReadMouse(IntBuffer buffer, int buffer_position); + private static native int nReadMouse(IntBuffer buffer, int buffer_position); public void grabMouse(boolean grab) { lockAWT(); nGrabMouse(grab); unlockAWT(); } - public native void nGrabMouse(boolean grab); + private static native void nGrabMouse(boolean grab); public int getNativeCursorCapabilities() { lockAWT(); - int caps = nGetNativeCursorCapabilities(); - unlockAWT(); - return caps; + try { + incDisplay(); + int caps = nGetNativeCursorCapabilities(); + decDisplay(); + return caps; + } catch (LWJGLException e) { + throw new RuntimeException(e); + } finally { + unlockAWT(); + } } - public native int nGetNativeCursorCapabilities(); + private static native int nGetNativeCursorCapabilities() throws LWJGLException; public void setNativeCursor(Object handle) throws LWJGLException { lockAWT(); nSetNativeCursor(handle); unlockAWT(); } - public native void nSetNativeCursor(Object handle) throws LWJGLException; + private static native void nSetNativeCursor(Object handle) throws LWJGLException; public int getMinCursorSize() { lockAWT(); @@ -279,7 +312,7 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return min_size; } - public native int nGetMinCursorSize(); + private static native int nGetMinCursorSize(); public int getMaxCursorSize() { lockAWT(); @@ -287,29 +320,32 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return max_size; } - public native int nGetMaxCursorSize(); + private static native int nGetMaxCursorSize(); /* Keyboard */ public void createKeyboard() throws LWJGLException { lockAWT(); - nCreateKeyboard(); - unlockAWT(); + try { + nCreateKeyboard(); + } finally { + unlockAWT(); + } } - public native void nCreateKeyboard() throws LWJGLException; + private static native void nCreateKeyboard() throws LWJGLException; public void destroyKeyboard() { lockAWT(); nDestroyKeyboard(); unlockAWT(); } - public native void nDestroyKeyboard(); + private static native void nDestroyKeyboard(); public void pollKeyboard(ByteBuffer keyDownBuffer) { lockAWT(); nPollKeyboard(keyDownBuffer); unlockAWT(); } - public native void nPollKeyboard(ByteBuffer keyDownBuffer); + private static native void nPollKeyboard(ByteBuffer keyDownBuffer); public int readKeyboard(IntBuffer buffer, int buffer_position) { lockAWT(); @@ -317,28 +353,38 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return count; } - public native int nReadKeyboard(IntBuffer buffer, int buffer_position); + private static native int nReadKeyboard(IntBuffer buffer, int buffer_position); public int isStateKeySet(int key) { return Keyboard.STATE_UNKNOWN; } - public native void nCreateCursor(ByteBuffer handle, int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException; + private static native void nCreateCursor(ByteBuffer handle, int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, int images_offset, IntBuffer delays, int delays_offset) throws LWJGLException; public Object createCursor(int width, int height, int xHotspot, int yHotspot, int numImages, IntBuffer images, IntBuffer delays) throws LWJGLException { lockAWT(); - ByteBuffer handle = BufferUtils.createByteBuffer(CURSOR_HANDLE_SIZE); - nCreateCursor(handle, width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1); - unlockAWT(); - return handle; + try { + incDisplay(); + try { + ByteBuffer handle = BufferUtils.createByteBuffer(CURSOR_HANDLE_SIZE); + nCreateCursor(handle, width, height, xHotspot, yHotspot, numImages, images, images.position(), delays, delays != null ? delays.position() : -1); + return handle; + } catch (LWJGLException e) { + decDisplay(); + throw e; + } + } finally { + unlockAWT(); + } } public void destroyCursor(Object cursorHandle) { lockAWT(); nDestroyCursor(cursorHandle); + decDisplay(); unlockAWT(); } - public native void nDestroyCursor(Object cursorHandle); + private static native void nDestroyCursor(Object cursorHandle); public int getPbufferCapabilities() { lockAWT(); @@ -346,50 +392,87 @@ final class LinuxDisplay implements DisplayImplementation { unlockAWT(); return caps; } - public native int nGetPbufferCapabilities(); + private static native int nGetPbufferCapabilities(); - public boolean isBufferLost(ByteBuffer handle) { + public boolean isBufferLost(PeerInfo handle) { return false; } - public void makePbufferCurrent(ByteBuffer handle) throws LWJGLException { +/* public void makePbufferCurrent(ByteBuffer handle) throws LWJGLException { lockAWT(); - nMakePbufferCurrent(handle); - unlockAWT(); + try { + nMakePbufferCurrent(handle); + } finally { + unlockAWT(); + } } - public native void nMakePbufferCurrent(ByteBuffer handle) throws LWJGLException; - - public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, + private static native void nMakePbufferCurrent(ByteBuffer handle) throws LWJGLException; +*/ +/* public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException { lockAWT(); - ByteBuffer handle = BufferUtils.createByteBuffer(PBUFFER_HANDLE_SIZE); - nCreatePbuffer(handle, width, height, pixel_format, pixelFormatCaps, pBufferAttribs, shared_pbuffer_handle); - unlockAWT(); - return handle; + try { + ByteBuffer handle = BufferUtils.createByteBuffer(PBUFFER_HANDLE_SIZE); + incDisplay(); + try { + nCreatePbuffer(handle, width, height, pixel_format, pixelFormatCaps, pBufferAttribs, shared_pbuffer_handle); + return handle; + } catch (LWJGLException e) { + decDisplay(); + throw e; + } + } finally { + unlockAWT(); + } } - private native void nCreatePbuffer(ByteBuffer handle, int width, int height, PixelFormat pixel_format, + private static native void nCreatePbuffer(ByteBuffer handle, int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException; - - public void destroyPbuffer(ByteBuffer handle) { +*/ + public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, + IntBuffer pixelFormatCaps, + IntBuffer pBufferAttribs) throws LWJGLException { lockAWT(); - nDestroyPbuffer(handle); + try { + incDisplay(); + try { + GLContext.loadOpenGLLibrary(); + try { + PeerInfo peer_info = new LinuxPbufferPeerInfo(width, height, pixel_format); + return peer_info; + } catch (LWJGLException e) { + GLContext.unloadOpenGLLibrary(); + throw e; + } + } catch (LWJGLException e) { + decDisplay(); + throw e; + } + } finally { + unlockAWT(); + } + } + + public void destroyPbuffer(PeerInfo handle) { + lockAWT(); + ((LinuxPbufferPeerInfo)handle).destroy(); + decDisplay(); + GLContext.unloadOpenGLLibrary(); unlockAWT(); } - public native void nDestroyPbuffer(ByteBuffer handle); - public void setPbufferAttrib(ByteBuffer handle, int attrib, int value) { + public void setPbufferAttrib(PeerInfo handle, int attrib, int value) { throw new UnsupportedOperationException(); } - public void bindTexImageToPbuffer(ByteBuffer handle, int buffer) { + public void bindTexImageToPbuffer(PeerInfo handle, int buffer) { throw new UnsupportedOperationException(); } - public void releaseTexImageFromPbuffer(ByteBuffer handle, int buffer) { + public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) { throw new UnsupportedOperationException(); } } diff --git a/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java new file mode 100644 index 00000000..92273cc3 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxDisplayPeerInfo.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +final class LinuxDisplayPeerInfo extends LinuxPeerInfo { + public LinuxDisplayPeerInfo(PixelFormat pixel_format) throws LWJGLException { + LinuxDisplay.lockAWT(); + initDefaultPeerInfo(getHandle(), pixel_format); + LinuxDisplay.unlockAWT(); + } + private static native void initDefaultPeerInfo(ByteBuffer peer_info_handle, PixelFormat pixel_format) throws LWJGLException; + + protected void doLockAndInitHandle() throws LWJGLException { + LinuxDisplay.lockAWT(); + initDrawable(getHandle()); + LinuxDisplay.unlockAWT(); + } + private static native void initDrawable(ByteBuffer peer_info_handle); + + protected void doUnlock() throws LWJGLException { + // NO-OP + } +} diff --git a/src/java/org/lwjgl/opengl/LinuxPeerInfo.java b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java new file mode 100644 index 00000000..b333a8d7 --- /dev/null +++ b/src/java/org/lwjgl/opengl/LinuxPeerInfo.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +abstract class LinuxPeerInfo extends PeerInfo { + private static final int PEER_HANDLE_SIZE = 64; + + public LinuxPeerInfo() { + super(BufferUtils.createByteBuffer(PEER_HANDLE_SIZE)); + } +} diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java index 3a85fcee..53dc44f3 100644 --- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java +++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java @@ -157,11 +157,11 @@ final class MacOSXDisplay implements DisplayImplementation { return new DisplayMode(awt_mode.getWidth(), awt_mode.getHeight(), bit_depth, refresh_rate); } - public DisplayMode init() { + public DisplayMode init() throws LWJGLException { return createLWJGLDisplayMode(MacOSXFrame.getDevice().getDisplayMode()); } - public DisplayMode[] getAvailableDisplayModes() { + public DisplayMode[] getAvailableDisplayModes() throws LWJGLException { java.awt.DisplayMode[] awt_modes = MacOSXFrame.getDevice().getDisplayModes(); List modes = new ArrayList(); for (int i = 0; i < awt_modes.length; i++) @@ -199,13 +199,17 @@ final class MacOSXDisplay implements DisplayImplementation { public native void setView(MacOSXGLCanvas canvas); - public native void swapBuffers(); +// public native void swapBuffers(); - public native void makeCurrent() throws LWJGLException; +// public native void makeCurrent() throws LWJGLException; - public native void createContext(PixelFormat pixel_format) throws LWJGLException; + public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException { + throw new RuntimeException("Not supported yet"); + } +// public native void createContext(PixelFormat pixel_format) throws LWJGLException; - public native void destroyContext(); + public native void destroyPeerInfo(); +// public native void destroyContext(); public void update() { if (frame.syncShouldUpdateContext()) { @@ -251,7 +255,7 @@ final class MacOSXDisplay implements DisplayImplementation { return MouseEventQueue.NUM_BUTTONS; } - public void createMouse() { + public void createMouse() throws LWJGLException { MacOSXGLCanvas canvas = frame.getCanvas(); this.mouse_queue = new MouseEventQueue(canvas.getWidth(), canvas.getHeight()); canvas.addMouseListener(mouse_queue); @@ -409,13 +413,19 @@ final class MacOSXDisplay implements DisplayImplementation { } } - public boolean isBufferLost(ByteBuffer handle) { + public boolean isBufferLost(PeerInfo handle) { return false; } - public native void makePbufferCurrent(ByteBuffer handle) throws LWJGLException; +// public native void makePbufferCurrent(ByteBuffer handle) throws LWJGLException; - public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, + public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, + IntBuffer pixelFormatCaps, + IntBuffer pBufferAttribs) throws LWJGLException { + throw new RuntimeException("Not yet supported"); + } + +/* public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException { ByteBuffer handle = BufferUtils.createByteBuffer(PBUFFER_HANDLE_SIZE); @@ -426,18 +436,19 @@ final class MacOSXDisplay implements DisplayImplementation { private native void nCreatePbuffer(ByteBuffer handle, int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException; +*/ +// public native void destroyPbuffer(ByteBuffer handle); + public native void destroyPbuffer(PeerInfo handle); - public native void destroyPbuffer(ByteBuffer handle); - - public void setPbufferAttrib(ByteBuffer handle, int attrib, int value) { + public void setPbufferAttrib(PeerInfo handle, int attrib, int value) { throw new UnsupportedOperationException(); } - public void bindTexImageToPbuffer(ByteBuffer handle, int buffer) { + public void bindTexImageToPbuffer(PeerInfo handle, int buffer) { throw new UnsupportedOperationException(); } - public void releaseTexImageFromPbuffer(ByteBuffer handle, int buffer) { + public void releaseTexImageFromPbuffer(PeerInfo handle, int buffer) { throw new UnsupportedOperationException(); } } diff --git a/src/java/org/lwjgl/opengl/Pbuffer.java b/src/java/org/lwjgl/opengl/Pbuffer.java index 779b43aa..03ad54c1 100644 --- a/src/java/org/lwjgl/opengl/Pbuffer.java +++ b/src/java/org/lwjgl/opengl/Pbuffer.java @@ -41,14 +41,13 @@ import org.lwjgl.Sys; *

* Pbuffer encapsulates an OpenGL pbuffer. *

- * Each instance of GL is only valid in the thread that creates it. In addition, only one instance of an OpenGL window or - * Pbuffer may be the current GL context in any one thread. To make a GL instance the current context, use makeCurrent(). + * + * This class is thread-safe. * * @author elias_naur * @version $Revision$ */ -public final class Pbuffer { - +public final class Pbuffer implements Drawable { /** * Indicates that Pbuffers can be created. */ @@ -137,7 +136,7 @@ public final class Pbuffer { /** * Handle to the native GL rendering context */ - private final ByteBuffer handle; + private final PeerInfo peer_info; /** * Width @@ -149,6 +148,10 @@ public final class Pbuffer { */ private final int height; + private final Context context; + + private boolean destroyed; + static { Sys.initialize(); } @@ -169,29 +172,40 @@ public final class Pbuffer { * @param height Pbuffer height * @param pixel_format Minimum Pbuffer context properties * @param renderTexture - * @param shared_context If non-null the Pbuffer will share display lists and textures with it. Otherwise, the Pbuffer will share + * @param shared_drawable If non-null the Pbuffer will share display lists and textures with it. Otherwise, the Pbuffer will share * with the Display context (if created). */ - public Pbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture, Pbuffer shared_context) throws LWJGLException { + public Pbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture, Drawable shared_drawable) throws LWJGLException { this.width = width; this.height = height; - this.handle = createPbuffer(width, height, pixel_format, renderTexture, shared_context != null ? shared_context.handle : null); + this.peer_info = createPbuffer(width, height, pixel_format, renderTexture); + Context shared_context = null; + if (shared_drawable != null) { + shared_context = shared_drawable.getContext(); + } else { + Drawable display_drawable = Display.getDrawable(); + if (display_drawable != null) + shared_context = display_drawable.getContext(); + } + this.context = new Context(peer_info, shared_context); } - private static ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture, ByteBuffer shared_context_handle) throws LWJGLException { - GLContext.loadOpenGLLibrary(); - try { - if ( renderTexture == null ) - return Display.getImplementation().createPbuffer(width, height, pixel_format, null, null, shared_context_handle); - else - return Display.getImplementation().createPbuffer(width, height, pixel_format, - renderTexture.pixelFormatCaps, - renderTexture.pBufferAttribs, - shared_context_handle); - } catch (LWJGLException e) { - GLContext.unloadOpenGLLibrary(); - throw e; - } + private static PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, RenderTexture renderTexture) throws LWJGLException { + if ( renderTexture == null ) + return Display.getImplementation().createPbuffer(width, height, pixel_format, null, null); + else + return Display.getImplementation().createPbuffer(width, height, pixel_format, + renderTexture.pixelFormatCaps, + renderTexture.pBufferAttribs); + } + + public Context getContext() { + return context; + } + + private void checkDestroyed() { + if (destroyed) + throw new IllegalStateException("Pbuffer is destroyed"); } /** @@ -201,17 +215,18 @@ public final class Pbuffer { * * @return true if the buffer is lost and destroyed, false if the buffer is valid. */ - public boolean isBufferLost() { - return Display.getImplementation().isBufferLost(handle); + public synchronized boolean isBufferLost() { + checkDestroyed(); + return Display.getImplementation().isBufferLost(peer_info); } /** * Method to make the Pbuffer context current. All subsequent OpenGL calls will go to this buffer. * @throws LWJGLException if the context could not be made current */ - public void makeCurrent() throws LWJGLException { - Display.getImplementation().makePbufferCurrent(handle); - GLContext.useContext(this); + public synchronized void makeCurrent() throws LWJGLException { + checkDestroyed(); + context.makeCurrent(); } /** @@ -227,17 +242,15 @@ public final class Pbuffer { * Destroys the Pbuffer. After this call, there will be no valid GL rendering context - regardless of whether this Pbuffer was * the current rendering context or not. */ - public void destroy() { + public synchronized void destroy() { + if (destroyed) + return; try { - makeCurrent(); - int error = GL11.glGetError(); - Display.getImplementation().destroyPbuffer(handle); - GLContext.useContext(null); - GLContext.unloadOpenGLLibrary(); - if (error != GL11.GL_NO_ERROR) - throw new OpenGLException(error); + context.forceDestroy(); + Display.getImplementation().destroyPbuffer(peer_info); + destroyed = true; } catch (LWJGLException e) { - // ignore exception + Sys.log("Exception occurred while destroying pbuffer: " + e); } } @@ -257,8 +270,9 @@ public final class Pbuffer { * @param attrib * @param value */ - public void setAttrib(int attrib, int value) { - Display.getImplementation().setPbufferAttrib(handle, attrib, value); + public synchronized void setAttrib(int attrib, int value) { + checkDestroyed(); + Display.getImplementation().setPbufferAttrib(peer_info, attrib, value); } /** @@ -268,8 +282,9 @@ public final class Pbuffer { * * @param buffer */ - public void bindTexImage(int buffer) { - Display.getImplementation().bindTexImageToPbuffer(handle, buffer); + public synchronized void bindTexImage(int buffer) { + checkDestroyed(); + Display.getImplementation().bindTexImageToPbuffer(peer_info, buffer); } /** @@ -277,21 +292,24 @@ public final class Pbuffer { * * @param buffer */ - public void releaseTexImage(int buffer) { - Display.getImplementation().releaseTexImageFromPbuffer(handle, buffer); + public synchronized void releaseTexImage(int buffer) { + checkDestroyed(); + Display.getImplementation().releaseTexImageFromPbuffer(peer_info, buffer); } /** * @return Returns the height. */ - public int getHeight() { + public synchronized int getHeight() { + checkDestroyed(); return height; } /** * @return Returns the width. */ - public int getWidth() { + public synchronized int getWidth() { + checkDestroyed(); return width; } } diff --git a/src/java/org/lwjgl/opengl/PeerInfo.java b/src/java/org/lwjgl/opengl/PeerInfo.java new file mode 100644 index 00000000..2bc32085 --- /dev/null +++ b/src/java/org/lwjgl/opengl/PeerInfo.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package org.lwjgl.opengl; + +import java.nio.ByteBuffer; + +import org.lwjgl.LWJGLException; +import org.lwjgl.Sys; + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ +abstract class PeerInfo { + private final ByteBuffer handle; + + protected PeerInfo(ByteBuffer handle) { + this.handle = handle; + } + + private final void lockAndInitHandle() throws LWJGLException { + doLockAndInitHandle(); + } + + public synchronized final void unlock() throws LWJGLException { + doUnlock(); + } + + protected abstract void doLockAndInitHandle() throws LWJGLException; + protected abstract void doUnlock() throws LWJGLException; + + public synchronized final ByteBuffer lockAndGetHandle() throws LWJGLException { + lockAndInitHandle(); + return getHandle(); + } + + protected final ByteBuffer getHandle() { + return handle; + } +} diff --git a/src/java/org/lwjgl/opengl/Win32Display.java b/src/java/org/lwjgl/opengl/Win32Display.java index cc5ea27a..61650494 100644 --- a/src/java/org/lwjgl/opengl/Win32Display.java +++ b/src/java/org/lwjgl/opengl/Win32Display.java @@ -58,25 +58,29 @@ final class Win32Display implements DisplayImplementation { public native void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException; public native String getAdapter(); public native String getVersion(); - public native DisplayMode init(); + public native DisplayMode init() throws LWJGLException; public native void setTitle(String title); public native boolean isCloseRequested(); public native boolean isVisible(); public native boolean isActive(); public native boolean isDirty(); - public native void swapBuffers(); - public native void makeCurrent() throws LWJGLException; - public native void createContext(PixelFormat pixel_format) throws LWJGLException; - public native void destroyContext(); +// public native void swapBuffers(); +// public native void makeCurrent() throws LWJGLException; + public PeerInfo createPeerInfo(PixelFormat pixel_format) throws LWJGLException { + throw new RuntimeException("Not supported yet"); + } +// public native void createContext(PixelFormat pixel_format) throws LWJGLException; +// public native void destroyContext(); + public native void destroyPeerInfo(); public native void update(); public native void setVSyncEnabled(boolean sync); public native void reshape(int x, int y, int width, int height); - public native DisplayMode[] getAvailableDisplayModes(); + public native DisplayMode[] getAvailableDisplayModes() throws LWJGLException; /* Mouse */ public native boolean hasWheel(); public native int getButtonCount(); - public native void createMouse(); + public native void createMouse() throws LWJGLException; public native void destroyMouse(); public native void pollMouse(IntBuffer coord_buffer, ByteBuffer buttons); public native int readMouse(IntBuffer buffer, int buffer_position); @@ -106,10 +110,17 @@ final class Win32Display implements DisplayImplementation { public native void destroyCursor(Object cursorHandle); public native int getPbufferCapabilities(); - public native boolean isBufferLost(ByteBuffer handle); - public native void makePbufferCurrent(ByteBuffer handle) throws LWJGLException; + public native boolean isBufferLost(PeerInfo handle); +// public native boolean isBufferLost(ByteBuffer handle); +// public native void makePbufferCurrent(ByteBuffer handle) throws LWJGLException; - public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, + public PeerInfo createPbuffer(int width, int height, PixelFormat pixel_format, + IntBuffer pixelFormatCaps, + IntBuffer pBufferAttribs) throws LWJGLException { + throw new RuntimeException("Not yet supported"); + } + +/* public ByteBuffer createPbuffer(int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException { ByteBuffer handle = BufferUtils.createByteBuffer(PBUFFER_HANDLE_SIZE); @@ -120,10 +131,14 @@ final class Win32Display implements DisplayImplementation { private native void nCreatePbuffer(ByteBuffer handle, int width, int height, PixelFormat pixel_format, IntBuffer pixelFormatCaps, IntBuffer pBufferAttribs, ByteBuffer shared_pbuffer_handle) throws LWJGLException; +*/ + public native void destroyPbuffer(PeerInfo handle); +// public native void destroyPbuffer(ByteBuffer handle); - public native void destroyPbuffer(ByteBuffer handle); - - public native void setPbufferAttrib(ByteBuffer handle, int attrib, int value); + public native void setPbufferAttrib(PeerInfo handle, int attrib, int value); + public native void bindTexImageToPbuffer(PeerInfo handle, int buffer); + public native void releaseTexImageFromPbuffer(PeerInfo handle, int buffer); +/* public native void setPbufferAttrib(ByteBuffer handle, int attrib, int value); public native void bindTexImageToPbuffer(ByteBuffer handle, int buffer); - public native void releaseTexImageFromPbuffer(ByteBuffer handle, int buffer); + public native void releaseTexImageFromPbuffer(ByteBuffer handle, int buffer);*/ } diff --git a/src/java/org/lwjgl/test/DisplayTest.java b/src/java/org/lwjgl/test/DisplayTest.java index 1364b0e0..346dc90b 100644 --- a/src/java/org/lwjgl/test/DisplayTest.java +++ b/src/java/org/lwjgl/test/DisplayTest.java @@ -54,7 +54,7 @@ public class DisplayTest { /** * Runs the tests */ - public void executeTest() { + public void executeTest() throws LWJGLException { currentTest(); queryModesTest(); setDisplayModeTest(); @@ -80,7 +80,7 @@ public class DisplayTest { /** * Tests querying for modes */ - private void queryModesTest() { + private void queryModesTest() throws LWJGLException { DisplayMode[] modes = null; System.out.println("==== Test query ===="); @@ -109,7 +109,7 @@ public class DisplayTest { /** * Tests setting display modes */ - private void setDisplayModeTest() { + private void setDisplayModeTest() throws LWJGLException { DisplayMode mode = null; DisplayMode[] modes = null; @@ -241,7 +241,7 @@ public class DisplayTest { * * @param args ignored */ - public static void main(String[] args) { + public static void main(String[] args) throws LWJGLException { new DisplayTest().executeTest(); } } diff --git a/src/java/org/lwjgl/test/SysTest.java b/src/java/org/lwjgl/test/SysTest.java index 05dea621..8cd8f89c 100644 --- a/src/java/org/lwjgl/test/SysTest.java +++ b/src/java/org/lwjgl/test/SysTest.java @@ -33,6 +33,7 @@ package org.lwjgl.test; import org.lwjgl.opengl.Display; import org.lwjgl.Sys; +import org.lwjgl.LWJGLException; /** * $Id$ @@ -75,7 +76,11 @@ public class SysTest { } // get some display modes, to force some debug info - Display.getAvailableDisplayModes(); + try { + Display.getAvailableDisplayModes(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } System.out.println("---- Test Debug ----\n"); } diff --git a/src/java/org/lwjgl/test/WindowCreationTest.java b/src/java/org/lwjgl/test/WindowCreationTest.java index 572c4918..0e6e1190 100644 --- a/src/java/org/lwjgl/test/WindowCreationTest.java +++ b/src/java/org/lwjgl/test/WindowCreationTest.java @@ -50,7 +50,7 @@ public class WindowCreationTest { * * @param args ignored params to app */ - public static void main(String[] args) { + public static void main(String[] args) throws LWJGLException { // get avaialble modes, and print out DisplayMode[] modes = Display.getAvailableDisplayModes(); System.out.println("Found " + modes.length + " display modes"); @@ -138,10 +138,10 @@ public class WindowCreationTest { * Sets the display mode for fullscreen mode */ protected static boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, diff --git a/src/java/org/lwjgl/test/input/HWCursorTest.java b/src/java/org/lwjgl/test/input/HWCursorTest.java index 98811a36..149129ce 100644 --- a/src/java/org/lwjgl/test/input/HWCursorTest.java +++ b/src/java/org/lwjgl/test/input/HWCursorTest.java @@ -76,10 +76,10 @@ public class HWCursorTest { * Sets the display mode for fullscreen mode */ protected boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, diff --git a/src/java/org/lwjgl/test/input/KeyboardTest.java b/src/java/org/lwjgl/test/input/KeyboardTest.java index cbeadf32..9dd949c0 100644 --- a/src/java/org/lwjgl/test/input/KeyboardTest.java +++ b/src/java/org/lwjgl/test/input/KeyboardTest.java @@ -78,10 +78,10 @@ public class KeyboardTest { * Sets the display mode for fullscreen mode */ protected boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, diff --git a/src/java/org/lwjgl/test/input/MouseCreationTest.java b/src/java/org/lwjgl/test/input/MouseCreationTest.java index 010dc31c..b531cbaa 100644 --- a/src/java/org/lwjgl/test/input/MouseCreationTest.java +++ b/src/java/org/lwjgl/test/input/MouseCreationTest.java @@ -72,10 +72,10 @@ public class MouseCreationTest { * Sets the display mode for fullscreen mode */ protected boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, diff --git a/src/java/org/lwjgl/test/openal/BasicTest.java b/src/java/org/lwjgl/test/openal/BasicTest.java index 33907098..f4450e97 100644 --- a/src/java/org/lwjgl/test/openal/BasicTest.java +++ b/src/java/org/lwjgl/test/openal/BasicTest.java @@ -109,10 +109,10 @@ public abstract class BasicTest { * Sets the display mode for fullscreen mode */ protected boolean setDisplayMode() { - // get modes - DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); - try { + // get modes + DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(640, 480, -1, -1, -1, -1, 60, 60); + org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + 640, "height=" + 480, diff --git a/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java b/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java index 4353f63e..83eabcca 100644 --- a/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java +++ b/src/java/org/lwjgl/test/opengl/FullScreenWindowedTest.java @@ -233,7 +233,7 @@ public class FullScreenWindowedTest { * Minimum required bits per pixel * @return */ - private DisplayMode findDisplayMode(int width, int height, int bpp) { + private DisplayMode findDisplayMode(int width, int height, int bpp) throws LWJGLException { DisplayMode[] modes = Display.getAvailableDisplayModes(); for (int i = 0; i < modes.length; i++) { if (modes[i].getWidth() == width && modes[i].getHeight() == height && modes[i].getBitsPerPixel() >= bpp && modes[i].getFrequency() <= 60) { diff --git a/src/java/org/lwjgl/test/opengl/PbufferTest.java b/src/java/org/lwjgl/test/opengl/PbufferTest.java index 4541cea2..28e201a0 100644 --- a/src/java/org/lwjgl/test/opengl/PbufferTest.java +++ b/src/java/org/lwjgl/test/opengl/PbufferTest.java @@ -341,7 +341,7 @@ public class PbufferTest { * @param bpp Minimum required bits per pixel * @return */ - private DisplayMode findDisplayMode(int width, int height, int bpp) { + private DisplayMode findDisplayMode(int width, int height, int bpp) throws LWJGLException { DisplayMode[] modes = Display.getAvailableDisplayModes(); for (int i = 0; i < modes.length; i++) { if (modes[i].getWidth() == width diff --git a/src/java/org/lwjgl/test/opengl/awt/AWTTest.java b/src/java/org/lwjgl/test/opengl/awt/AWTTest.java index 8fcd39ad..cbe7ee4e 100644 --- a/src/java/org/lwjgl/test/opengl/awt/AWTTest.java +++ b/src/java/org/lwjgl/test/opengl/awt/AWTTest.java @@ -5,9 +5,11 @@ package org.lwjgl.test.opengl.awt; import java.awt.Frame; +import java.awt.Graphics; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import org.lwjgl.LWJGLException; import org.lwjgl.opengl.AWTGLCanvas; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.glu.GLU; @@ -30,31 +32,54 @@ public class AWTTest extends Frame { /** * C'tor */ - public AWTTest() { + public AWTTest() throws LWJGLException { setTitle("LWJGL AWT Canvas Test"); setSize(640, 320); setLayout(null); add(canvas0 = new AWTGLCanvas() { - protected void doPaint() { - GL11.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); - GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); + public void paint(Graphics g) { + try { + makeCurrent(); + GL11.glViewport(0, 0, getWidth(), getHeight()); + GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glLoadIdentity(); + GLU.gluOrtho2D(0.0f, (float) getWidth(), 0.0f, (float) getHeight()); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + GL11.glPushMatrix(); + GL11.glColor3f(1f, 1f, 0f); + GL11.glTranslatef(getWidth() / 2.0f, getHeight() / 2.0f, 0.0f); + GL11.glRotatef(angle, 0f, 0f, 1.0f); + GL11.glRectf(-50.0f, -50.0f, 50.0f, 50.0f); + GL11.glPopMatrix(); + swapBuffers(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } } }); canvas0.setBounds(0, 0, 320, 320); add(canvas1 = new AWTGLCanvas() { - protected void doPaint() { - GL11.glViewport(0, 0, getWidth(), getHeight()); - GL11.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); - GL11.glMatrixMode(GL11.GL_PROJECTION); - GL11.glLoadIdentity(); - GLU.gluOrtho2D(0.0f, (float) getWidth(), 0.0f, (float) getHeight()); - GL11.glMatrixMode(GL11.GL_MODELVIEW); - GL11.glPushMatrix(); - GL11.glTranslatef(getWidth() / 2.0f, getHeight() / 2.0f, 0.0f); - GL11.glRotatef(angle, 0f, 0f, 1.0f); - GL11.glRectf(-50.0f, -50.0f, 50.0f, 50.0f); - GL11.glPopMatrix(); + public void paint(Graphics g) { + try { + makeCurrent(); + GL11.glViewport(0, 0, getWidth(), getHeight()); + GL11.glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); + GL11.glMatrixMode(GL11.GL_PROJECTION); + GL11.glLoadIdentity(); + GLU.gluOrtho2D(0.0f, (float) getWidth(), 0.0f, (float) getHeight()); + GL11.glMatrixMode(GL11.GL_MODELVIEW); + GL11.glPushMatrix(); + GL11.glTranslatef(getWidth() / 2.0f, getHeight() / 2.0f, 0.0f); + GL11.glRotatef(2*angle, 0f, 0f, -1.0f); + GL11.glRectf(-50.0f, -50.0f, 50.0f, 50.0f); + GL11.glPopMatrix(); + swapBuffers(); + } catch (LWJGLException e) { + throw new RuntimeException(e); + } } }); canvas1.setBounds(320, 0, 320, 320); @@ -64,6 +89,7 @@ public class AWTTest extends Frame { } }); setResizable(true); + setVisible(true); new Thread() { { @@ -72,6 +98,7 @@ public class AWTTest extends Frame { public void run() { for (;;) { angle += 1.0f; + canvas0.repaint(); canvas1.repaint(); try { sleep(20); @@ -83,7 +110,7 @@ public class AWTTest extends Frame { }.start(); } - public static void main(String[] args) { - new AWTTest().setVisible(true); + public static void main(String[] args) throws LWJGLException { + new AWTTest(); } } diff --git a/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java b/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java index 0aa6412c..d4639044 100644 --- a/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java +++ b/src/java/org/lwjgl/test/opengl/pbuffers/PbufferTest.java @@ -345,7 +345,7 @@ public final class PbufferTest { * * @return */ - private DisplayMode findDisplayMode(int width, int height, int bpp) { + private DisplayMode findDisplayMode(int width, int height, int bpp) throws LWJGLException { DisplayMode[] modes = Display.getAvailableDisplayModes(); for ( int i = 0; i < modes.length; i++ ) { if ( modes[i].getWidth() == width diff --git a/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java b/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java index 938d9479..2afd395b 100644 --- a/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java +++ b/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java @@ -122,19 +122,19 @@ public final class ShadersTest { if ( args.length != 1 ) argsError(); - DisplayMode[] modes = Display.getAvailableDisplayModes(); - - DisplayMode displayMode; - - displayMode = chooseMode(modes, 1024, 768); - if ( displayMode == null ) - displayMode = chooseMode(modes, 800, 600); - if ( displayMode == null ) - displayMode = chooseMode(modes, 640, 480); - if ( displayMode == null ) - kill("Failed to set an appropriate display mode."); - try { + DisplayMode[] modes = Display.getAvailableDisplayModes(); + + DisplayMode displayMode; + + displayMode = chooseMode(modes, 1024, 768); + if ( displayMode == null ) + displayMode = chooseMode(modes, 800, 600); + if ( displayMode == null ) + displayMode = chooseMode(modes, 640, 480); + if ( displayMode == null ) + kill("Failed to set an appropriate display mode."); + System.out.println("Setting display mode to: " + displayMode); Display.setDisplayMode(displayMode); Display.create(new PixelFormat(8, 24, 0)); diff --git a/src/java/org/lwjgl/util/Display.java b/src/java/org/lwjgl/util/Display.java index 1987ac39..e5966c66 100644 --- a/src/java/org/lwjgl/util/Display.java +++ b/src/java/org/lwjgl/util/Display.java @@ -37,6 +37,7 @@ import java.util.Arrays; import java.util.Comparator; import org.lwjgl.Sys; +import org.lwjgl.LWJGLException; import org.lwjgl.opengl.DisplayMode; /** @@ -65,7 +66,7 @@ public final class Display { * @return an array of matching display modes */ public static DisplayMode[] getAvailableDisplayModes(int minWidth, int minHeight, int maxWidth, int maxHeight, int minBPP, int maxBPP, - int minFreq, int maxFreq) + int minFreq, int maxFreq) throws LWJGLException { // First get the available display modes DisplayMode[] modes = org.lwjgl.opengl.Display.getAvailableDisplayModes(); diff --git a/src/native/common/awt_tools.h b/src/native/common/awt_tools.h new file mode 100644 index 00000000..ac641d70 --- /dev/null +++ b/src/native/common/awt_tools.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include + +typedef struct { + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo *dsi; +} AWTSurfaceLock; diff --git a/src/native/common/org_lwjgl_opengl_AWTSurfaceLock.c b/src/native/common/org_lwjgl_opengl_AWTSurfaceLock.c new file mode 100644 index 00000000..0575e383 --- /dev/null +++ b/src/native/common/org_lwjgl_opengl_AWTSurfaceLock.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include +#include "org_lwjgl_opengl_AWTSurfaceLock.h" +#include "awt_tools.h" +#include "common_tools.h" + +#define WAIT_DELAY 100 + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_AWTSurfaceLock_lockAndInitHandle + (JNIEnv *env, jclass clazz, jobject lock_buffer_handle, jobject canvas) { + if ((*env)->GetDirectBufferCapacity(env, lock_buffer_handle) < sizeof(AWTSurfaceLock)) { + throwException(env, "Lock handle buffer not large enough"); + return; + } + AWTSurfaceLock *awt_lock = (AWTSurfaceLock *)(*env)->GetDirectBufferAddress(env, lock_buffer_handle); + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo *dsi; + awt.version = JAWT_VERSION_1_4; + while (true) { + if (JAWT_GetAWT(env, &awt) == JNI_FALSE) { + throwException(env, "Could not get the JAWT interface"); + return; + } + + ds = awt.GetDrawingSurface(env, canvas); + if (ds == NULL) { + throwException(env, "Could not get the drawing surface"); + return; + } + + if((ds->Lock(ds) & JAWT_LOCK_ERROR) != 0) { + awt.FreeDrawingSurface(ds); + throwException(env, "Could not lock the drawing surface"); + return; + } + + dsi = ds->GetDrawingSurfaceInfo(ds); + if (dsi != NULL) + break; + + printfDebug("Could not get drawing surface info, retrying... \n"); + ds->Unlock(ds); + awt.FreeDrawingSurface(ds); + usleep(WAIT_DELAY); + } + awt_lock->awt = awt; + awt_lock->ds = ds; + awt_lock->dsi = dsi; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_AWTSurfaceLock_nUnlock + (JNIEnv *env, jclass clazz, jobject lock_buffer_handle) { + AWTSurfaceLock *awt_lock = (AWTSurfaceLock *)(*env)->GetDirectBufferAddress(env, lock_buffer_handle); + awt_lock->ds->FreeDrawingSurfaceInfo(awt_lock->dsi); + awt_lock->ds->Unlock(awt_lock->ds); + awt_lock->awt.FreeDrawingSurface(awt_lock->ds); +} + diff --git a/src/native/linux/Window.h b/src/native/linux/Window.h index 67c8809d..ec822eae 100644 --- a/src/native/linux/Window.h +++ b/src/native/linux/Window.h @@ -49,13 +49,12 @@ #include "extgl.h" #include "extgl_glx.h" - extern GLXFBConfig *chooseVisualGLX13(JNIEnv *env, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffer); /* * release input (keyboard, mouse) */ extern void handleMessages(JNIEnv *env); - extern bool checkXError(JNIEnv *env); + extern bool checkXError(JNIEnv *env, Display *display); extern Atom getWarpAtom(void); /* * Various functions to release/acquire keyboard and mouse @@ -81,19 +80,6 @@ */ extern int getWindowHeight(void); - /* - * Increment display usage (and possible open it). - * Return the display handle. - * If the function fails, it will return NULL - * and throw a java exception through the env argument - */ - extern Display *incDisplay(JNIEnv *env); - - /* - * Decrement display usage and possibly release it - */ - extern void decDisplay(void); - /* * get the current display */ @@ -108,21 +94,6 @@ * get the current window */ extern Window getCurrentWindow(void); - - /* - * Release the context if it is current - */ - extern bool releaseContext(GLXContext context); - - /* - * get the current context - */ - extern GLXContext getDisplayContext(void); - - /* - * get the current GLXFBConfig for the current context - */ - extern GLXFBConfig getCurrentGLXFBConfig(void); /* * Return true if we are in fullscreen mode @@ -134,8 +105,4 @@ */ extern bool isLegacyFullscreen(void); - /* - * convert bit-per-pixel to bits-per-element - */ - extern int convertToBPE(int bpp); #endif /* _LWJGL_WINDOW_H_INCLUDED_ */ diff --git a/src/native/linux/context.c b/src/native/linux/context.c new file mode 100644 index 00000000..e1570d05 --- /dev/null +++ b/src/native/linux/context.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * Include file to access public window features + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include +#include +#include "extgl_glx.h" +#include "context.h" + +XVisualInfo *getVisualInfoFromPeerInfo(JNIEnv *env, X11PeerInfo *peer_info) { + XVisualInfo *vis_info; + if (!peer_info->glx13) { + XVisualInfo template; + template.visualid = peer_info->config.glx_config.visualid; + template.depth = peer_info->config.glx_config.depth; + template.screen = peer_info->screen; + int num_infos; + vis_info = XGetVisualInfo(peer_info->display, VisualIDMask | VisualScreenMask | VisualDepthMask, &template, &num_infos); + if (vis_info == NULL) { + throwException(env, "Could not find VisualInfo from peer info"); + return NULL; + } + // Check the assumption from GLX 1.3 docs that a VisualInfo is uniquely identified by its + // {VisualID, screen, depth} tuple + if (num_infos != 1) { + XFree(vis_info); + throwException(env, "No unique VisualInfo matches peer info"); + return NULL; + } + } else { + GLXFBConfig *configs = getFBConfigFromPeerInfo(env, peer_info); + if (configs == NULL) + return NULL; + vis_info = glXGetVisualFromFBConfig(peer_info->display, configs[0]); + if (vis_info == NULL) + throwException(env, "Could not get VisualInfo from GLX 1.3 config"); + XFree(configs); + } + return vis_info; +} + +GLXFBConfig *getFBConfigFromPeerInfo(JNIEnv *env, X11PeerInfo *peer_info) { + int attribs[] = {GLX_FBCONFIG_ID, peer_info->config.glx13_config.config_id}; + int num_elements; + GLXFBConfig *configs = glXChooseFBConfig(peer_info->display, peer_info->screen, attribs, &num_elements); + if (configs == NULL) { + throwException(env, "Could not find GLX 1.3 config from peer info"); + return NULL; + } + // Check that only one FBConfig matches the config id + if (num_elements != 1) { + XFree(configs); + throwException(env, "No unique GLX 1.3 config matches peer info"); + return NULL; + } + return configs; +} + +static int convertToBPE(int bpp) { + int bpe; + switch (bpp) { + case 32: + case 24: + bpe = 8; + break; + case 16: /* Fall through */ + default: + bpe = 4; + break; + } + return bpe; +} + +static GLXFBConfig *chooseVisualGLX13FromBPP(JNIEnv *env, Display *disp, int screen, jobject pixel_format, int bpp, int drawable_type, bool double_buffer) { + jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); + int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I")); + int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I")); + int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I")); + int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I")); + int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I")); + int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I")); + int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I")); + bool stereo = (bool)(*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z")); + + int bpe = convertToBPE(bpp); + int accum_bpe = convertToBPE(accum_bpp); + attrib_list_t attrib_list; + initAttribList(&attrib_list); + putAttrib(&attrib_list, GLX_RENDER_TYPE); putAttrib(&attrib_list, GLX_RGBA_BIT); + putAttrib(&attrib_list, GLX_DOUBLEBUFFER); putAttrib(&attrib_list, double_buffer ? True : False); + putAttrib(&attrib_list, GLX_DRAWABLE_TYPE); putAttrib(&attrib_list, drawable_type); + putAttrib(&attrib_list, GLX_DEPTH_SIZE); putAttrib(&attrib_list, depth); + putAttrib(&attrib_list, GLX_RED_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_GREEN_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_BLUE_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_ALPHA_SIZE); putAttrib(&attrib_list, alpha); + putAttrib(&attrib_list, GLX_STENCIL_SIZE); putAttrib(&attrib_list, stencil); + putAttrib(&attrib_list, GLX_AUX_BUFFERS); putAttrib(&attrib_list, num_aux_buffers); + putAttrib(&attrib_list, GLX_ACCUM_RED_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_GREEN_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_BLUE_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_ALPHA_SIZE); putAttrib(&attrib_list, accum_alpha); + putAttrib(&attrib_list, GLX_STEREO); putAttrib(&attrib_list, stereo ? True : False); + if (samples > 0 && extension_flags.GLX_ARB_multisample) { + putAttrib(&attrib_list, GLX_SAMPLE_BUFFERS_ARB); putAttrib(&attrib_list, 1); + putAttrib(&attrib_list, GLX_SAMPLES_ARB); putAttrib(&attrib_list, samples); + } + putAttrib(&attrib_list, None); putAttrib(&attrib_list, None); + int num_formats = 0; + GLXFBConfig* configs = glXChooseFBConfig(disp, screen, attrib_list.attribs, &num_formats); + if (num_formats > 0) { + return configs; + } else { + if (configs != NULL) + XFree(configs); + return NULL; + } +} + +GLXFBConfig *chooseVisualGLX13(JNIEnv *env, Display *disp, int screen, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffer) { + jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); + int bpp; + if (use_display_bpp) { + bpp = XDefaultDepthOfScreen(XScreenOfDisplay(disp, screen)); + GLXFBConfig *configs = chooseVisualGLX13FromBPP(env, disp, screen, pixel_format, bpp, drawable_type, double_buffer); + if (configs != NULL) + return configs; + else + bpp = 16; + } else + bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "bpp", "I")); + return chooseVisualGLX13FromBPP(env, disp, screen, pixel_format, bpp, drawable_type, double_buffer); +} + +static XVisualInfo *chooseVisualGLXFromBPP(JNIEnv *env, Display *disp, int screen, jobject pixel_format, int bpp, bool double_buffer) { + jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); + int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I")); + int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I")); + int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I")); + int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I")); + int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I")); + int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I")); + int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I")); + bool stereo = (bool)(*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z")); + + int bpe = convertToBPE(bpp); + int accum_bpe = convertToBPE(accum_bpp); + attrib_list_t attrib_list; + initAttribList(&attrib_list); + putAttrib(&attrib_list, GLX_RGBA); + putAttrib(&attrib_list, GLX_DOUBLEBUFFER); + putAttrib(&attrib_list, GLX_DEPTH_SIZE); putAttrib(&attrib_list, depth); + putAttrib(&attrib_list, GLX_RED_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_GREEN_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_BLUE_SIZE); putAttrib(&attrib_list, bpe); + putAttrib(&attrib_list, GLX_ALPHA_SIZE); putAttrib(&attrib_list, alpha); + putAttrib(&attrib_list, GLX_STENCIL_SIZE); putAttrib(&attrib_list, stencil); + putAttrib(&attrib_list, GLX_AUX_BUFFERS); putAttrib(&attrib_list, num_aux_buffers); + putAttrib(&attrib_list, GLX_ACCUM_RED_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_GREEN_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_BLUE_SIZE); putAttrib(&attrib_list, accum_bpe); + putAttrib(&attrib_list, GLX_ACCUM_ALPHA_SIZE); putAttrib(&attrib_list, accum_alpha); + if (stereo) + putAttrib(&attrib_list, GLX_STEREO); + if (samples > 0 && extension_flags.GLX_ARB_multisample) { + putAttrib(&attrib_list, GLX_SAMPLE_BUFFERS_ARB); putAttrib(&attrib_list, 1); + putAttrib(&attrib_list, GLX_SAMPLES_ARB); putAttrib(&attrib_list, samples); + } + putAttrib(&attrib_list, None); + return glXChooseVisual(disp, screen, attrib_list.attribs); +} + +XVisualInfo *chooseVisualGLX(JNIEnv *env, Display *disp, int screen, jobject pixel_format, bool use_display_bpp, bool double_buffer) { + jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); + int bpp; + if (use_display_bpp) { + bpp = XDefaultDepthOfScreen(XScreenOfDisplay(disp, screen)); + XVisualInfo *vis_info = chooseVisualGLXFromBPP(env, disp, screen, pixel_format, bpp, double_buffer); + if (vis_info != NULL) + return vis_info; + else + bpp = 16; + } else + bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "bpp", "I")); + return chooseVisualGLXFromBPP(env, disp, screen, pixel_format, bpp, double_buffer); +} + +static void dumpVisualInfo(JNIEnv *env, Display *display, XVisualInfo *vis_info) { + int alpha, depth, stencil, r, g, b; + int sample_buffers = 0; + int samples = 0; + glXGetConfig(display, vis_info, GLX_RED_SIZE, &r); + glXGetConfig(display, vis_info, GLX_GREEN_SIZE, &g); + glXGetConfig(display, vis_info, GLX_BLUE_SIZE, &b); + glXGetConfig(display, vis_info, GLX_ALPHA_SIZE, &alpha); + glXGetConfig(display, vis_info, GLX_DEPTH_SIZE, &depth); + glXGetConfig(display, vis_info, GLX_STENCIL_SIZE, &stencil); + if (extension_flags.GLX_ARB_multisample) { + glXGetConfig(display, vis_info, GLX_SAMPLE_BUFFERS_ARB, &sample_buffers); + glXGetConfig(display, vis_info, GLX_SAMPLES_ARB, &samples); + } + printfDebugJava(env, "Pixel format info: r = %d, g = %d, b = %d, a = %d, depth = %d, stencil = %d, sample buffers = %d, samples = %d", r, g, b, alpha, depth, stencil, sample_buffers, samples); +} + +bool initPeerInfo(JNIEnv *env, jobject peer_info_handle, Display *display, int screen, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffered, bool force_glx13) { + if ((*env)->GetDirectBufferCapacity(env, peer_info_handle) < sizeof(X11PeerInfo)) { + throwException(env, "Handle too small"); + return false; + } + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + if (!extgl_InitGLX(env, display, screen)) { + throwException(env, "Could not init GLX"); + return false; + } + if (!extension_flags.GLX13 && force_glx13) { + throwException(env, "GLX13 is required, but is not available"); + return false; + } + peer_info->glx13 = extension_flags.GLX13; + if (peer_info->glx13) { + GLXFBConfig *configs = chooseVisualGLX13(env, display, screen, pixel_format, use_display_bpp, drawable_type, double_buffered); + if (isDebugEnabled()) { + XVisualInfo *vis_info = glXGetVisualFromFBConfig(display, configs[0]); + if (vis_info != NULL) { + dumpVisualInfo(env, display, vis_info); + XFree(vis_info); + } + } + int config_id; + int result = glXGetFBConfigAttrib(display, configs[0], GLX_FBCONFIG_ID, &config_id); + XFree(configs); + if (result != Success) { + throwException(env, "Could not choose GLX13 config"); + return false; + } + peer_info->config.glx13_config.config_id = config_id; + } else { + XVisualInfo *vis_info = chooseVisualGLX(env, display, screen, pixel_format, use_display_bpp, double_buffered); + if (vis_info == NULL) { + throwException(env, "Could not choose visual"); + return false; + } + peer_info->config.glx_config.visualid = vis_info->visualid; + peer_info->config.glx_config.depth = vis_info->depth; + peer_info->screen = vis_info->screen; + if (isDebugEnabled()) + dumpVisualInfo(env, display, vis_info); + XFree(vis_info); + } + peer_info->display = display; + peer_info->screen = screen; + peer_info->drawable = None; + return true; +} diff --git a/src/native/linux/context.h b/src/native/linux/context.h new file mode 100644 index 00000000..3be0e502 --- /dev/null +++ b/src/native/linux/context.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * Include file to access public window features + * + * @author elias_naur + * @version $Revision$ + */ + +#ifndef _LWJGL_CONTEXT_H_INCLUDED_ +#define _LWJGL_CONTEXT_H_INCLUDED_ + +#include +#include +#include +#include +#include "extgl_glx.h" + +typedef struct { + VisualID visualid; + int depth; +} GLXConfig; + +typedef struct { + GLXFBConfigID config_id; +} GLX13Config; + +typedef struct { + Display *display; + int screen; + GLXDrawable drawable; + // This flag determines the appropriate glx struct + bool glx13; + union { + GLXConfig glx_config; + GLX13Config glx13_config; + } config; +} X11PeerInfo; + +/* GLX 1.3 chooser */ +extern GLXFBConfig *chooseVisualGLX13(JNIEnv *env, Display *disp, int screen, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffer); + +/* Default GLX chooser*/ +extern XVisualInfo *chooseVisualGLX(JNIEnv *env, Display *disp, int screen, jobject pixel_format, bool use_display_bpp, bool double_buffer); + +extern XVisualInfo *getVisualInfoFromPeerInfo(JNIEnv *env, X11PeerInfo *peer_info); +extern GLXFBConfig *getFBConfigFromPeerInfo(JNIEnv *env, X11PeerInfo *peer_info); + +extern bool initPeerInfo(JNIEnv *env, jobject peer_info_handle, Display *display, int screen, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffered, bool force_glx13); + +#endif /* _LWJGL_CONTEXT_H_INCLUDED_ */ diff --git a/src/native/linux/org_lwjgl_input_Cursor.c b/src/native/linux/org_lwjgl_input_Cursor.c index 63f7b77c..bf7690c4 100644 --- a/src/native/linux/org_lwjgl_input_Cursor.c +++ b/src/native/linux/org_lwjgl_input_Cursor.c @@ -48,23 +48,19 @@ #include "common_tools.h" JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetNativeCursorCapabilities - (JNIEnv *env, jobject this) { + (JNIEnv *env, jclass clazz) { int caps = 0; - Display *disp = incDisplay(env); - if (disp == NULL) - return caps; XcursorBool argb_supported = XcursorSupportsARGB(getDisplay()); XcursorBool anim_supported = XcursorSupportsAnim(getDisplay()); if (argb_supported) caps |= org_lwjgl_input_Cursor_CURSOR_8_BIT_ALPHA | org_lwjgl_input_Cursor_CURSOR_ONE_BIT_TRANSPARENCY; if (anim_supported) caps |= org_lwjgl_input_Cursor_CURSOR_ANIMATION; - decDisplay(); return caps; } JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetMinCursorSize - (JNIEnv *env, jobject this) + (JNIEnv *env, jclass clazz) { unsigned int width_return = 0; unsigned int height_return = 0; @@ -73,7 +69,7 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetMinCursorSize } JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetMaxCursorSize - (JNIEnv *env, jobject this) + (JNIEnv *env, jclass clazz) { unsigned int width_return = 0; unsigned int height_return = 0; @@ -82,15 +78,12 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetMaxCursorSize } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateCursor - (JNIEnv *env, jobject this, jobject handle_buffer, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset) + (JNIEnv *env, jclass clazz, jobject handle_buffer, jint width, jint height, jint x_hotspot, jint y_hotspot, jint num_images, jobject image_buffer, jint images_offset, jobject delay_buffer, jint delays_offset) { if ((*env)->GetDirectBufferCapacity(env, handle_buffer) < sizeof(Cursor)) { throwException(env, "Handle buffer not large enough"); return; } - Display *disp = incDisplay(env); - if (disp == NULL) - return; const int *delays = NULL; if (delay_buffer != NULL) delays = (const int *)(*env)->GetDirectBufferAddress(env, delay_buffer) + delays_offset; @@ -98,7 +91,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateCursor int stride = width*height; XcursorImages *cursor_images = XcursorImagesCreate(num_images); if (cursor_images == NULL) { - decDisplay(); throwException(env, "Could not allocate cursor."); return; } @@ -114,14 +106,13 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateCursor cursor_images->images[i] = cursor_image; } Cursor *cursor = (Cursor *)(*env)->GetDirectBufferAddress(env, handle_buffer); - *cursor = XcursorImagesLoadCursor(disp, cursor_images); + *cursor = XcursorImagesLoadCursor(getDisplay(), cursor_images); XcursorImagesDestroy(cursor_images); } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyCursor - (JNIEnv *env, jobject this, jobject cursor_handle_buffer) + (JNIEnv *env, jclass clazz, jobject cursor_handle_buffer) { Cursor *cursor = (Cursor *)(*env)->GetDirectBufferAddress(env, cursor_handle_buffer); XFreeCursor(getDisplay(), *cursor); - decDisplay(); } diff --git a/src/native/linux/org_lwjgl_input_Keyboard.c b/src/native/linux/org_lwjgl_input_Keyboard.c index 15a36a2e..009745e2 100644 --- a/src/native/linux/org_lwjgl_input_Keyboard.c +++ b/src/native/linux/org_lwjgl_input_Keyboard.c @@ -119,11 +119,8 @@ static void setupIMEventMask() { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard - (JNIEnv * env, jobject this) + (JNIEnv * env, jclass clazz) { - Display *disp = incDisplay(env); - if (disp == NULL) - return; int i; for (i = 0; i < KEYBOARD_SIZE; i++) key_map[i] = i; @@ -169,12 +166,11 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyKeyboard - (JNIEnv * env, jobject this) + (JNIEnv * env, jclass clazz) { closeUnicodeStructs(); ungrabKeyboard(); created = false; - decDisplay(); } static unsigned char getKeycode(XKeyEvent *event) { @@ -280,13 +276,13 @@ void handleKeyEvent(XKeyEvent *event) { bufferEvent(event); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollKeyboard(JNIEnv * env, jobject this, jobject buffer) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollKeyboard(JNIEnv * env, jclass clazz, jobject buffer) { unsigned char *new_keyboard_buffer = (unsigned char *)(*env)->GetDirectBufferAddress(env, buffer); handleMessages(env); memcpy(new_keyboard_buffer, key_buf, KEYBOARD_SIZE*sizeof(unsigned char)); } -JNIEXPORT int JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadKeyboard(JNIEnv * env, jobject this, jobject buffer, jint buffer_position) { +JNIEXPORT int JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadKeyboard(JNIEnv * env, jclass clazz, jobject buffer, jint buffer_position) { handleMessages(env); jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer); int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position; diff --git a/src/native/linux/org_lwjgl_input_Mouse.c b/src/native/linux/org_lwjgl_input_Mouse.c index 231b0125..4cda1aa0 100644 --- a/src/native/linux/org_lwjgl_input_Mouse.c +++ b/src/native/linux/org_lwjgl_input_Mouse.c @@ -190,7 +190,7 @@ static void doWarpPointer(int center_x, int center_y) { XWarpPointer(getDisplay(), None, getCurrentWindow(), 0, 0, 0, 0, center_x, center_y); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetNativeCursor(JNIEnv *env, jobject this, jobject cursor_handle) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetNativeCursor(JNIEnv *env, jclass clazz, jobject cursor_handle) { if (cursor_handle != NULL) { Cursor *cursor = (Cursor *)(*env)->GetDirectBufferAddress(env, cursor_handle); current_cursor = *cursor; @@ -204,18 +204,14 @@ static void reset(void) { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateMouse - (JNIEnv * env, jobject this) + (JNIEnv * env, jclass clazz) { - Display *disp = incDisplay(env); - if (disp == NULL) - return; int i; last_y = last_x = accum_dx = accum_dy = accum_dz = 0; reset(); for (i = 0; i < org_lwjgl_opengl_LinuxDisplay_NUM_BUTTONS; i++) buttons[i] = 0; if (!blankCursor(env)) { - decDisplay(); return; } current_cursor = None; @@ -226,12 +222,11 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateMouse } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyMouse - (JNIEnv * env, jobject this) + (JNIEnv * env, jclass clazz) { ungrabPointer(); XFreeCursor(getDisplay(), blank_cursor); created = false; - decDisplay(); } static unsigned char mapButton(XButtonEvent *event) { @@ -313,7 +308,7 @@ void handlePointerMotion(XMotionEvent *event) { doHandlePointerMotion(event->x_root, event->y_root, event->x, event->y); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * env, jobject this, jobject coord_buffer_obj, jobject button_buffer_obj) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * env, jclass clazz, jobject coord_buffer_obj, jobject button_buffer_obj) { int *coords = (int *)(*env)->GetDirectBufferAddress(env, coord_buffer_obj); int coords_length = (*env)->GetDirectBufferCapacity(env, coord_buffer_obj); unsigned char *buttons_buffer = (unsigned char *)(*env)->GetDirectBufferAddress(env, button_buffer_obj); @@ -340,14 +335,14 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nPollMouse(JNIEnv * en buttons_buffer[i] = buttons[i]; } -JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadMouse(JNIEnv *env, jobject this, jobject buffer, jint buffer_position) { +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReadMouse(JNIEnv *env, jclass clazz, jobject buffer, jint buffer_position) { jint* buffer_ptr = (jint *)(*env)->GetDirectBufferAddress(env, buffer); int buffer_size = ((*env)->GetDirectBufferCapacity(env, buffer))/sizeof(jint) - buffer_position; handleMessages(env); return copyEvents(&event_queue, buffer_ptr + buffer_position, buffer_size); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabMouse(JNIEnv * env, jobject this, jboolean new_grab) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGrabMouse(JNIEnv * env, jclass clazz, jboolean new_grab) { Window root_return, child_return; int root_x, root_y, win_x, win_y; unsigned int mask_return; diff --git a/src/native/linux/org_lwjgl_opengl_Display.c b/src/native/linux/org_lwjgl_opengl_Display.c index b6404f4c..a53745ca 100644 --- a/src/native/linux/org_lwjgl_opengl_Display.c +++ b/src/native/linux/org_lwjgl_opengl_Display.c @@ -51,10 +51,12 @@ #include "extgl.h" #include "extgl_glx.h" #include "Window.h" +#include "context.h" #include "display.h" #include "org_lwjgl_opengl_LinuxDisplay.h" +#include "org_lwjgl_opengl_LinuxDisplayPeerInfo.h" -#define USEGLX13 extension_flags.GLX13 +//#define USEGLX13 extension_flags.GLX13 #define ERR_MSG_SIZE 1024 typedef struct { @@ -69,10 +71,10 @@ typedef struct { typedef enum {FULLSCREEN_LEGACY, FULLSCREEN_NETWM, WINDOWED} window_mode; -static GLXContext display_context = NULL; // OpenGL rendering context -static GLXFBConfig *configs = NULL; -static GLXWindow glx_window; -static XVisualInfo *vis_info = NULL; +//static GLXContext display_context = NULL; // OpenGL rendering context +//static GLXFBConfig *configs = NULL; +static GLXWindow glx_window = None; +//static XVisualInfo *vis_info = NULL; static Atom delete_atom; static Colormap cmap; @@ -97,20 +99,16 @@ static bool async_x_error; static char error_message[ERR_MSG_SIZE]; static Atom warp_atom; -GLXFBConfig getCurrentGLXFBConfig(void) { - return configs[0]; -} - -GLXContext getDisplayContext(void) { +/*GLXContext getDisplayContext(void) { return display_context; } - +*/ int getCurrentScreen(void) { return current_screen; } -bool checkXError(JNIEnv *env) { - XSync(getDisplay(), False); +bool checkXError(JNIEnv *env, Display *disp) { + XSync(disp, False); if (async_x_error) { async_x_error = false; if (env != NULL) @@ -137,7 +135,7 @@ Display *getDisplay(void) { return display_connection; } -Display *incDisplay(JNIEnv *env) { +static Display *incDisplay(JNIEnv *env) { if (display_connection_usage == 0) { async_x_error = false; XSetErrorHandler(errorHandler); @@ -149,6 +147,7 @@ Display *incDisplay(JNIEnv *env) { printfDebugJava(env, "Could not open X display connection"); return NULL; } + current_screen = XDefaultScreen(getDisplay()); warp_atom = XInternAtom(display_connection, "_LWJGL_WARP", False); } async_x_error = false; @@ -160,7 +159,7 @@ Atom getWarpAtom(void) { return warp_atom; } -void decDisplay(void) { +static void decDisplay(void) { display_connection_usage--; if (display_connection_usage == 0) { XCloseDisplay(display_connection); @@ -318,15 +317,37 @@ static void setWindowTitle(const char *title) { XStoreName(getDisplay(), current_win, title); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetTitle(JNIEnv * env, jobject this, jstring title_obj) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_incDisplay(JNIEnv *env, jclass clazz) { + incDisplay(env); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_decDisplay(JNIEnv *env, jclass clazz) { + decDisplay(); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDrawable(JNIEnv *env, jclass clazz, jobject peer_info_handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + if (peer_info->glx13) + peer_info->drawable = glx_window; + else + peer_info->drawable = getCurrentWindow(); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplayPeerInfo_initDefaultPeerInfo(JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject pixel_format) { + initPeerInfo(env, peer_info_handle, getDisplay(), getCurrentScreen(), pixel_format, true, GLX_WINDOW_BIT, true, false); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetTitle(JNIEnv * env, jclass clazz, jstring title_obj) { char * title = GetStringNativeChars(env, title_obj); setWindowTitle(title); free(title); } static void destroyWindow(JNIEnv *env) { - if (USEGLX13) + if (glx_window != None) { glXDestroyWindow(getDisplay(), glx_window); + glx_window = None; + } XDestroyWindow(getDisplay(), current_win); XFreeColormap(getDisplay(), cmap); setRepeatMode(env, AutoRepeatModeDefault); @@ -357,11 +378,11 @@ static bool isNetWMFullscreenSupported(JNIEnv *env) { return supported; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv *env, jobject this, jint x, jint y, jint width, jint height) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nReshape(JNIEnv *env, jclass clazz, jint x, jint y, jint width, jint height) { XMoveWindow(getDisplay(), getCurrentWindow(), x, y); } -static bool createWindow(JNIEnv* env, int x, int y, int width, int height) { +static bool createWindow(JNIEnv* env, X11PeerInfo *peer_info, int x, int y, int width, int height) { bool undecorated = getBooleanProperty(env, "org.lwjgl.opengl.Window.undecorated"); dirty = true; focused = true; @@ -378,6 +399,9 @@ static bool createWindow(JNIEnv* env, int x, int y, int width, int height) { current_width = width; current_height = height; root_win = RootWindow(getDisplay(), getCurrentScreen()); + XVisualInfo *vis_info = getVisualInfoFromPeerInfo(env, peer_info); + if (vis_info == NULL) + return false; cmap = XCreateColormap(getDisplay(), root_win, vis_info->visual, AllocNone); attribs.colormap = cmap; attribs.event_mask = ExposureMask | /*FocusChangeMask | */VisibilityChangeMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; @@ -389,7 +413,8 @@ static bool createWindow(JNIEnv* env, int x, int y, int width, int height) { attribs.override_redirect = True; } win = XCreateWindow(getDisplay(), root_win, x, y, width, height, 0, vis_info->depth, InputOutput, vis_info->visual, attribmask, &attribs); - if (!checkXError(env)) { + XFree(vis_info); + if (!checkXError(env, getDisplay())) { XFreeColormap(getDisplay(), cmap); return false; } @@ -418,7 +443,7 @@ static bool createWindow(JNIEnv* env, int x, int y, int width, int height) { waitMapped(win); XClearWindow(getDisplay(), win); setRepeatMode(env, AutoRepeatModeOff); - if (!checkXError(env)) { + if (!checkXError(env, getDisplay())) { destroyWindow(env); return false; } @@ -438,12 +463,12 @@ int getWindowHeight(void) { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate - (JNIEnv *env, jobject this) + (JNIEnv *env, jclass clazz) { handleMessages(env); } -bool releaseContext(GLXContext context) { +/*bool releaseContext(GLXContext context) { if (glXGetCurrentContext() != context) return true; if (USEGLX13) @@ -460,145 +485,13 @@ static bool makeCurrent(void) { } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nMakeCurrent - (JNIEnv *env, jobject this) + (JNIEnv *env, jclass clazz) { if (!makeCurrent()) throwException(env, "Could not make display context current"); } - -int convertToBPE(int bpp) { - int bpe; - switch (bpp) { - case 32: - case 24: - bpe = 8; - break; - case 16: /* Fall through */ - default: - bpe = 4; - break; - } - return bpe; -} - -static GLXFBConfig *chooseVisualGLX13FromBPP(JNIEnv *env, jobject pixel_format, int bpp, int drawable_type, bool double_buffer) { - jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); - int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I")); - int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I")); - int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I")); - int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I")); - int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I")); - int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I")); - int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I")); - bool stereo = (bool)(*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z")); - - int bpe = convertToBPE(bpp); - int accum_bpe = convertToBPE(accum_bpp); - attrib_list_t attrib_list; - initAttribList(&attrib_list); - putAttrib(&attrib_list, GLX_RENDER_TYPE); putAttrib(&attrib_list, GLX_RGBA_BIT); - putAttrib(&attrib_list, GLX_DOUBLEBUFFER); putAttrib(&attrib_list, double_buffer ? True : False); - putAttrib(&attrib_list, GLX_DRAWABLE_TYPE); putAttrib(&attrib_list, drawable_type); - putAttrib(&attrib_list, GLX_DEPTH_SIZE); putAttrib(&attrib_list, depth); - putAttrib(&attrib_list, GLX_RED_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_GREEN_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_BLUE_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_ALPHA_SIZE); putAttrib(&attrib_list, alpha); - putAttrib(&attrib_list, GLX_STENCIL_SIZE); putAttrib(&attrib_list, stencil); - putAttrib(&attrib_list, GLX_AUX_BUFFERS); putAttrib(&attrib_list, num_aux_buffers); - putAttrib(&attrib_list, GLX_ACCUM_RED_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_GREEN_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_BLUE_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_ALPHA_SIZE); putAttrib(&attrib_list, accum_alpha); - putAttrib(&attrib_list, GLX_STEREO); putAttrib(&attrib_list, stereo ? True : False); - if (samples > 0 && extension_flags.GLX_ARB_multisample) { - putAttrib(&attrib_list, GLX_SAMPLE_BUFFERS_ARB); putAttrib(&attrib_list, 1); - putAttrib(&attrib_list, GLX_SAMPLES_ARB); putAttrib(&attrib_list, samples); - } - putAttrib(&attrib_list, None); putAttrib(&attrib_list, None); - int num_formats = 0; - GLXFBConfig* configs = glXChooseFBConfig(getDisplay(), getCurrentScreen(), attrib_list.attribs, &num_formats); - if (num_formats > 0) { - return configs; - } else { - if (configs != NULL) - XFree(configs); - return NULL; - } -} - -GLXFBConfig *chooseVisualGLX13(JNIEnv *env, jobject pixel_format, bool use_display_bpp, int drawable_type, bool double_buffer) { - jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); - int bpp; - if (use_display_bpp) { - bpp = XDefaultDepthOfScreen(XScreenOfDisplay(getDisplay(), getCurrentScreen())); - GLXFBConfig *configs = chooseVisualGLX13FromBPP(env, pixel_format, bpp, drawable_type, double_buffer); - if (configs != NULL) - return configs; - else - bpp = 16; - } else - bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "bpp", "I")); - return chooseVisualGLX13FromBPP(env, pixel_format, bpp, drawable_type, double_buffer); -} - -static XVisualInfo *chooseVisualGLX(JNIEnv *env, jobject pixel_format) { - int bpp = XDefaultDepthOfScreen(XScreenOfDisplay(getDisplay(), getCurrentScreen())); - jclass cls_pixel_format = (*env)->GetObjectClass(env, pixel_format); - int alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "alpha", "I")); - int depth = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "depth", "I")); - int stencil = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stencil", "I")); - int samples = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "samples", "I")); - int num_aux_buffers = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "num_aux_buffers", "I")); - int accum_bpp = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_bpp", "I")); - int accum_alpha = (int)(*env)->GetIntField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "accum_alpha", "I")); - bool stereo = (bool)(*env)->GetBooleanField(env, pixel_format, (*env)->GetFieldID(env, cls_pixel_format, "stereo", "Z")); - - int bpe = convertToBPE(bpp); - int accum_bpe = convertToBPE(accum_bpp); - attrib_list_t attrib_list; - initAttribList(&attrib_list); - putAttrib(&attrib_list, GLX_RGBA); - putAttrib(&attrib_list, GLX_DOUBLEBUFFER); - putAttrib(&attrib_list, GLX_DEPTH_SIZE); putAttrib(&attrib_list, depth); - putAttrib(&attrib_list, GLX_RED_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_GREEN_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_BLUE_SIZE); putAttrib(&attrib_list, bpe); - putAttrib(&attrib_list, GLX_ALPHA_SIZE); putAttrib(&attrib_list, alpha); - putAttrib(&attrib_list, GLX_STENCIL_SIZE); putAttrib(&attrib_list, stencil); - putAttrib(&attrib_list, GLX_AUX_BUFFERS); putAttrib(&attrib_list, num_aux_buffers); - putAttrib(&attrib_list, GLX_ACCUM_RED_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_GREEN_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_BLUE_SIZE); putAttrib(&attrib_list, accum_bpe); - putAttrib(&attrib_list, GLX_ACCUM_ALPHA_SIZE); putAttrib(&attrib_list, accum_alpha); - if (stereo) - putAttrib(&attrib_list, GLX_STEREO); - if (samples > 0 && extension_flags.GLX_ARB_multisample) { - putAttrib(&attrib_list, GLX_SAMPLE_BUFFERS_ARB); putAttrib(&attrib_list, 1); - putAttrib(&attrib_list, GLX_SAMPLES_ARB); putAttrib(&attrib_list, samples); - } - putAttrib(&attrib_list, None); - return glXChooseVisual(getDisplay(), getCurrentScreen(), attrib_list.attribs); -} - -static void dumpVisualInfo(JNIEnv *env, XVisualInfo *vis_info) { - int alpha, depth, stencil, r, g, b; - int sample_buffers = 0; - int samples = 0; - glXGetConfig(getDisplay(), vis_info, GLX_RED_SIZE, &r); - glXGetConfig(getDisplay(), vis_info, GLX_GREEN_SIZE, &g); - glXGetConfig(getDisplay(), vis_info, GLX_BLUE_SIZE, &b); - glXGetConfig(getDisplay(), vis_info, GLX_ALPHA_SIZE, &alpha); - glXGetConfig(getDisplay(), vis_info, GLX_DEPTH_SIZE, &depth); - glXGetConfig(getDisplay(), vis_info, GLX_STENCIL_SIZE, &stencil); - if (extension_flags.GLX_ARB_multisample) { - glXGetConfig(getDisplay(), vis_info, GLX_SAMPLE_BUFFERS_ARB, &sample_buffers); - glXGetConfig(getDisplay(), vis_info, GLX_SAMPLES_ARB, &samples); - } - printfDebugJava(env, "Pixel format info: r = %d, g = %d, b = %d, a = %d, depth = %d, stencil = %d, sample buffers = %d, samples = %d", r, g, b, alpha, depth, stencil, sample_buffers, samples); -} - -static void destroyContext(void) { +*/ +/*static void destroyContext(void) { if (USEGLX13) { XFree(configs); configs = NULL; @@ -609,9 +502,9 @@ static void destroyContext(void) { glXDestroyContext(getDisplay(), display_context); display_context = NULL; } - -static bool initWindowGLX13(JNIEnv *env, jobject pixel_format) { - configs = chooseVisualGLX13(env, pixel_format, true, GLX_WINDOW_BIT, true); +*/ +/*static bool initWindowGLX13(JNIEnv *env, jobject pixel_format) { + configs = chooseVisualGLX13(env, getDisplay(), getCurrentScreen(), pixel_format, true, GLX_WINDOW_BIT, true); if (configs == NULL) { throwException(env, "Could not find a matching pixel format"); return false; @@ -636,7 +529,7 @@ static bool initWindowGLX13(JNIEnv *env, jobject pixel_format) { throwException(env, "Could not get visual from FB config"); return false; } - if (!checkXError(env)) { + if (!checkXError(env, getDisplay())) { glXDestroyContext(getDisplay(), display_context); XFree(configs); XFree(vis_info); @@ -646,13 +539,11 @@ static bool initWindowGLX13(JNIEnv *env, jobject pixel_format) { } static bool initWindowGLX(JNIEnv *env, jobject pixel_format) { - vis_info = chooseVisualGLX(env, pixel_format); + vis_info = chooseVisualGLX(env, getDisplay(), getCurrentScreen(), pixel_format, true, true); if (vis_info == NULL) { throwException(env, "Could not find a matching pixel format"); return false; } - if (isDebugEnabled()) - dumpVisualInfo(env, vis_info); display_context = glXCreateContext(getDisplay(), vis_info, NULL, True); if (display_context == NULL) { XFree(vis_info); @@ -666,39 +557,39 @@ static bool initWindowGLX(JNIEnv *env, jobject pixel_format) { throwException(env, "Could not create a direct GLX context"); return false; } - if (!checkXError(env)) { + if (!checkXError(env, getDisplay())) { glXDestroyContext(getDisplay(), display_context); XFree(vis_info); return false; } return true; } - -JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jobject this) { +*/ +JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jclass clazz) { return getAvailableDisplayModes(env, getCurrentScreen()); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jobject this, jobject mode) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNIEnv *env, jclass clazz, jobject mode) { switchDisplayMode(env, mode, getCurrentScreen()); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jobject this) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jclass clazz) { resetDisplayMode(env, getCurrentScreen(), false); } -JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jobject this) { +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz) { return (jint)getGammaRampLength(env, getCurrentScreen()); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jobject this, jobject gamma_buffer) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jclass clazz, jobject gamma_buffer) { setGammaRamp(env, gamma_buffer, getCurrentScreen()); } -JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nInit(JNIEnv *env, jobject this) { +JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nInit(JNIEnv *env, jclass clazz) { return initDisplay(env, getCurrentScreen()); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateContext(JNIEnv *env, jobject this, jobject pixel_format) { +/*JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateContext(JNIEnv *env, jclass clazz, jobject pixel_format) { Display *disp = incDisplay(env); if (disp == NULL) { return; @@ -719,13 +610,13 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateContext(JNIEnv if (!result) decDisplay(); } - -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyContext(JNIEnv *env, jobject this) { +*/ +/*JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyContext(JNIEnv *env, jclass clazz) { destroyContext(); decDisplay(); } - -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jobject this, jobject mode, jboolean fullscreen, int x, int y) { +*/ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject mode, jboolean fullscreen, jint x, jint y) { bool current_fullscreen = fullscreen == JNI_TRUE; if (current_fullscreen) { if (getCurrentDisplayModeExtension() == XRANDR && isNetWMFullscreenSupported(env)) { @@ -737,30 +628,37 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateWindow(JNIEnv * } } else current_window_mode = WINDOWED; + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + GLXFBConfig *fb_config = NULL; + if (peer_info->glx13) { + fb_config = getFBConfigFromPeerInfo(env, peer_info); + if (fb_config == NULL) + return; + } jclass cls_displayMode = (*env)->GetObjectClass(env, mode); jfieldID fid_width = (*env)->GetFieldID(env, cls_displayMode, "width", "I"); jfieldID fid_height = (*env)->GetFieldID(env, cls_displayMode, "height", "I"); int width = (*env)->GetIntField(env, mode, fid_width); int height = (*env)->GetIntField(env, mode, fid_height); - bool window_created = createWindow(env, x, y, width, height); + bool window_created = createWindow(env, peer_info, x, y, width, height); if (!window_created) { return; } - if (isDebugEnabled()) - dumpVisualInfo(env, vis_info); - if (USEGLX13) - glx_window = glXCreateWindow(getDisplay(), configs[0], getCurrentWindow(), NULL); - if (!checkXError(env)) { + if (peer_info->glx13) { + glx_window = glXCreateWindow(getDisplay(), *fb_config, getCurrentWindow(), NULL); + XFree(fb_config); + } + if (!checkXError(env, getDisplay())) { glXDestroyWindow(getDisplay(), glx_window); destroyWindow(env); } } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyWindow(JNIEnv *env, jobject this) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyWindow(JNIEnv *env, jclass clazz) { destroyWindow(env); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwapBuffers(JNIEnv * env, jobject this) +/*JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwapBuffers(JNIEnv * env, jclass clazz) { dirty = false; if (USEGLX13) @@ -768,33 +666,33 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwapBuffers(JNIEnv * else glXSwapBuffers(getDisplay(), getCurrentWindow()); } - +*/ JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsDirty - (JNIEnv *env, jobject this) { + (JNIEnv *env, jclass clazz) { bool result = dirty; dirty = false; return result ? JNI_TRUE : JNI_FALSE; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsVisible - (JNIEnv *env, jobject this) { + (JNIEnv *env, jclass clazz) { return minimized ? JNI_FALSE : JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsCloseRequested - (JNIEnv *env, jobject this) { + (JNIEnv *env, jclass clazz) { bool saved = closerequested; closerequested = false; return saved; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nIsActive - (JNIEnv *env, jobject this) { + (JNIEnv *env, jclass clazz) { return focused || isLegacyFullscreen() ? JNI_TRUE : JNI_FALSE; } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetVSyncEnabled - (JNIEnv *env, jobject this, jboolean sync) +/*JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetVSyncEnabled + (JNIEnv *env, jclass clazz, jboolean sync) { if (extension_flags.GLX_SGI_swap_control) { bool vsync = sync == JNI_TRUE ? true : false; @@ -805,8 +703,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetVSyncEnabled } } } - -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_lockAWT(JNIEnv *env, jobject this) { +*/ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_lockAWT(JNIEnv *env, jclass clazz) { JAWT jawt; jawt.version = JAWT_VERSION_1_4; if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) { @@ -816,7 +714,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_lockAWT(JNIEnv *env, j jawt.Lock(env); } -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_unlockAWT(JNIEnv *env, jobject this) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_unlockAWT(JNIEnv *env, jclass clazz) { JAWT jawt; jawt.version = JAWT_VERSION_1_4; if (JAWT_GetAWT(env, &jawt) != JNI_TRUE) { diff --git a/src/native/linux/org_lwjgl_opengl_LinuxAWTGLCanvasPeerInfo.c b/src/native/linux/org_lwjgl_opengl_LinuxAWTGLCanvasPeerInfo.c new file mode 100644 index 00000000..28c04a07 --- /dev/null +++ b/src/native/linux/org_lwjgl_opengl_LinuxAWTGLCanvasPeerInfo.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include +#include +#include +#include +#include "awt_tools.h" +#include "org_lwjgl_opengl_LinuxAWTGLCanvasPeerInfo.h" +#include "extgl_glx.h" +#include "context.h" +#include "Window.h" + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxAWTGLCanvasPeerInfo_nInitHandle + (JNIEnv *env, jclass clazz, int screen, jobject lock_buffer_handle, jobject peer_info_handle) { + if ((*env)->GetDirectBufferCapacity(env, peer_info_handle) < sizeof(X11PeerInfo)) { + throwException(env, "PeerInfo handle buffer not large enough"); + return; + } + const AWTSurfaceLock *awt_lock = (AWTSurfaceLock *)(*env)->GetDirectBufferAddress(env, lock_buffer_handle); + X11PeerInfo *peer_info = (X11PeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); + // Get the platform-specific drawing info + JAWT_X11DrawingSurfaceInfo *dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)awt_lock->dsi->platformInfo; + + peer_info->display = dsi_x11->display; + peer_info->screen = screen; + peer_info->drawable = dsi_x11->drawable; + peer_info->glx13 = false; + peer_info->config.glx_config.visualid = dsi_x11->visualID; + peer_info->config.glx_config.depth = dsi_x11->depth; +} diff --git a/src/native/linux/org_lwjgl_opengl_LinuxCanvasImplementation.c b/src/native/linux/org_lwjgl_opengl_LinuxCanvasImplementation.c new file mode 100644 index 00000000..17374780 --- /dev/null +++ b/src/native/linux/org_lwjgl_opengl_LinuxCanvasImplementation.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include +#include +#include "org_lwjgl_opengl_LinuxCanvasImplementation.h" +#include "extgl_glx.h" +#include "context.h" +#include "Window.h" + +JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxCanvasImplementation_nFindVisualIDFromFormat + (JNIEnv *env, jclass clazz, jint screen, jobject pixel_format) { + if (!extgl_InitGLX(env, getDisplay(), screen)) { + throwException(env, "Could not initialize GLX"); + return -1; + } + XVisualInfo *vis_info = chooseVisualGLX(env, getDisplay(), screen, pixel_format, true, true); + if (vis_info == NULL) { + throwException(env, "Could not choose a VisualInfo"); + return -1; + } + + VisualID vis_id = vis_info->visualid; + XFree(vis_info); + return vis_id; +} diff --git a/src/native/linux/org_lwjgl_opengl_LinuxContextImplementation.c b/src/native/linux/org_lwjgl_opengl_LinuxContextImplementation.c new file mode 100644 index 00000000..54a43526 --- /dev/null +++ b/src/native/linux/org_lwjgl_opengl_LinuxContextImplementation.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/** + * $Id$ + * + * @author elias_naur + * @version $Revision$ + */ + +#include +#include +#include +#include +#include "org_lwjgl_opengl_LinuxContextImplementation.h" +#include "extgl_glx.h" +#include "context.h" +#include "common_tools.h" +#include "Window.h" + +typedef struct { + bool glx13; + GLXContext context; +} X11Context; + +static bool checkContext(JNIEnv *env, Display *display, GLXContext context) { + if (context == NULL) { + throwException(env, "Could not create GLX context"); + return false; + } + jboolean allow_software_acceleration = getBooleanProperty(env, "org.lwjgl.opengl.Display.allowSoftwareOpenGL"); + if (!allow_software_acceleration && glXIsDirect(display, context) == False) { + glXDestroyContext(display, context); + throwException(env, "Could not create a direct GLX context"); + return false; + } + return true; +} + +static void createContextGLX13(JNIEnv *env, X11PeerInfo *peer_info, X11Context *context_info, GLXContext shared_context) { + GLXFBConfig *config = getFBConfigFromPeerInfo(env, peer_info); + if (config == NULL) + return; + GLXContext context = glXCreateNewContext(peer_info->display, *config, GLX_RGBA_TYPE, shared_context, True); + XFree(config); + if (!checkContext(env, peer_info->display, context)) + return; + context_info->glx13 = true; + context_info->context = context; +} + +static void createContextGLX(JNIEnv *env, X11PeerInfo *peer_info, X11Context *context_info, GLXContext shared_context) { + XVisualInfo *vis_info = getVisualInfoFromPeerInfo(env, peer_info); + if (vis_info == NULL) + return; + GLXContext context = glXCreateContext(peer_info->display, vis_info, shared_context, True); + XFree(vis_info); + if (!checkContext(env, peer_info->display, context)) + return; + context_info->glx13 = false; + context_info->context = context; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nSetVSync + (JNIEnv *env, jclass clazz, jboolean sync) +{ + if (extension_flags.GLX_SGI_swap_control) { + int interval = sync == JNI_TRUE ? 1 : 0; + glXSwapIntervalSGI(interval); + } +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nCreate + (JNIEnv *env , jclass clazz, jobject peer_handle, jobject context_handle, jobject shared_context_handle) { + if ((*env)->GetDirectBufferCapacity(env, context_handle) < sizeof(X11Context)) { + throwException(env, "Handle buffer not large enough"); + return; + } + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_handle); + X11Context *context_info = (*env)->GetDirectBufferAddress(env, context_handle); + + if (!extgl_InitGLX(env, peer_info->display, peer_info->screen)) { + throwException(env, "Could not initialize GLX"); + return; + } + GLXContext shared_context = NULL; + if (shared_context_handle != NULL) { + X11Context *shared_context_info = (*env)->GetDirectBufferAddress(env, shared_context_handle); + shared_context = shared_context_info->context; + } + if (peer_info->glx13) { + createContextGLX13(env, peer_info, context_info, shared_context); + } else { + createContextGLX(env, peer_info, context_info, shared_context); + } +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nDestroy + (JNIEnv *env, jclass clazz, jobject peer_handle, jobject context_handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_handle); + X11Context *context_info = (*env)->GetDirectBufferAddress(env, context_handle); + glXDestroyContext(peer_info->display, context_info->context); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nReleaseCurrentContext + (JNIEnv *env , jclass clazz, jobject peer_info_handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + Bool result; + if (extension_flags.GLX13) { + result = glXMakeContextCurrent(peer_info->display, None, None, NULL); + } else { + result = glXMakeCurrent(peer_info->display, None, NULL); + } + if (!result) + throwException(env, "Could not release current context"); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nMakeCurrent + (JNIEnv *env, jclass clazz, jobject peer_info_handle, jobject context_handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + X11Context *context_info = (*env)->GetDirectBufferAddress(env, context_handle); + Bool result; + if (context_info->glx13) { + result = glXMakeContextCurrent(peer_info->display, peer_info->drawable, peer_info->drawable, context_info->context); + } else { + result = glXMakeCurrent(peer_info->display, peer_info->drawable, context_info->context); + } + if (!result) + throwException(env, "Could not make context current"); +} + +JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nIsCurrent + (JNIEnv *env, jclass clazz, jobject context_handle) { + X11Context *context_info = (*env)->GetDirectBufferAddress(env, context_handle); + return context_info->context == glXGetCurrentContext(); +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxContextImplementation_nSwapBuffers + (JNIEnv *env, jclass clazz, jobject peer_info_handle) { + X11PeerInfo *peer_info = (*env)->GetDirectBufferAddress(env, peer_info_handle); + glXSwapBuffers(peer_info->display, peer_info->drawable); +} diff --git a/src/native/linux/org_lwjgl_opengl_Pbuffer.c b/src/native/linux/org_lwjgl_opengl_Pbuffer.c index c7a94403..f0438492 100644 --- a/src/native/linux/org_lwjgl_opengl_Pbuffer.c +++ b/src/native/linux/org_lwjgl_opengl_Pbuffer.c @@ -40,38 +40,38 @@ */ #include -#include "org_lwjgl_opengl_LinuxDisplay.h" +#include "org_lwjgl_opengl_LinuxPbufferPeerInfo.h" #include "org_lwjgl_opengl_Pbuffer.h" #include "extgl.h" +#include "context.h" #include "Window.h" #include "common_tools.h" - +/* typedef struct _PbufferInfo { GLXPbuffer buffer; GLXContext context; } PbufferInfo; - +*/ static bool isPbuffersSupported() { // Only support the GLX 1.3 Pbuffers and ignore the GLX_SGIX_pbuffer extension return extension_flags.GLX13 ? org_lwjgl_opengl_Pbuffer_PBUFFER_SUPPORTED : 0; } JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetPbufferCapabilities - (JNIEnv *env, jobject this) + (JNIEnv *env, jclass clazz) { return isPbuffersSupported() ? org_lwjgl_opengl_Pbuffer_PBUFFER_SUPPORTED : 0; } -static void destroyPbuffer(PbufferInfo *buffer_info) { +/*static void destroyPbuffer(PbufferInfo *buffer_info) { GLXPbuffer buffer = buffer_info->buffer; GLXContext context = buffer_info->context; glXDestroyPbuffer(getDisplay(), buffer); releaseContext(context); glXDestroyContext(getDisplay(), context); - decDisplay(); } - -static bool checkPbufferCaps(JNIEnv *env, GLXFBConfig config, int width, int height) { +*/ +/*static bool checkPbufferCaps(JNIEnv *env, GLXFBConfig config, int width, int height) { int max; int result = glXGetFBConfigAttrib(getDisplay(), config, GLX_MAX_PBUFFER_WIDTH, &max); if (result != Success) { @@ -95,7 +95,7 @@ static bool checkPbufferCaps(JNIEnv *env, GLXFBConfig config, int width, int hei } static bool createPbufferUsingUniqueContext(JNIEnv *env, PbufferInfo *pbuffer_info, jobject pixel_format, int width, int height, const int *buffer_attribs, GLXContext shared_context) { - GLXFBConfig *configs = chooseVisualGLX13(env, pixel_format, false, GLX_PBUFFER_BIT, false); + GLXFBConfig *configs = chooseVisualGLX13(env, getDisplay(), getCurrentScreen(), pixel_format, false, GLX_PBUFFER_BIT, false); if (configs == NULL) { throwException(env, "No matching pixel format"); return false; @@ -123,16 +123,43 @@ static bool createPbufferUsingUniqueContext(JNIEnv *env, PbufferInfo *pbuffer_in pbuffer_info->buffer = buffer; return true; } +*/ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxPbufferPeerInfo_nInitHandle + (JNIEnv *env, jclass clazz, jobject peer_info_handle, jint width, jint height, jobject pixel_format) { + if (!extgl_InitGLX(env, getDisplay(), getCurrentScreen()) || !isPbuffersSupported()) { + throwException(env, "No Pbuffer support"); + return; + } + bool result = initPeerInfo(env, peer_info_handle, getDisplay(), getCurrentScreen(), pixel_format, false, GLX_PBUFFER_BIT, false, true); + if (!result) + return; + const int buffer_attribs[] = {GLX_PBUFFER_WIDTH, width, + GLX_PBUFFER_HEIGHT, height, + GLX_PRESERVED_CONTENTS, True, + GLX_LARGEST_PBUFFER, False, + None, None}; -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreatePbuffer(JNIEnv *env, jobject this, jobject handle_buffer, jint width, jint height, jobject pixel_format, jobject pixelFormatCaps, jobject pBufferAttribs, jobject shared_context_handle_buffer) + X11PeerInfo *peer_info = (X11PeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); + GLXFBConfig *config = getFBConfigFromPeerInfo(env, peer_info); + GLXPbuffer buffer = glXCreatePbuffer(peer_info->display, *config, buffer_attribs); + XFree(config); + peer_info->drawable = buffer; +} + +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxPbufferPeerInfo_nDestroy + (JNIEnv *env, jclass clazz, jobject peer_info_handle) { + X11PeerInfo *peer_info = (X11PeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); + glXDestroyPbuffer(peer_info->display, peer_info->drawable); +} +/* +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreatePbuffer(JNIEnv *env, jclass clazz, jobject handle_buffer, jint width, jint height, jobject pixel_format, jobject pixelFormatCaps, jobject pBufferAttribs, jobject shared_context_handle_buffer) { - Display *disp = incDisplay(env); - if (disp == NULL) { + if ((*env)->GetDirectBufferCapacity(env, handle_buffer) < sizeof(PbufferInfo)) { + throwException(env, "Handle buffer not large enough"); return; } int current_screen = getCurrentScreen(); - if (!extgl_InitGLX(env, disp, current_screen) || !isPbuffersSupported()) { - decDisplay(); + if (!extgl_InitGLX(env, getDisplay(), current_screen) || !isPbuffersSupported()) { throwException(env, "No Pbuffer support"); return; } @@ -143,11 +170,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreatePbuffer(JNIEnv GLX_LARGEST_PBUFFER, False, None, None}; - if ((*env)->GetDirectBufferCapacity(env, handle_buffer) < sizeof(PbufferInfo)) { - decDisplay(); - throwException(env, "Handle buffer not large enough"); - return; - } GLXContext shared_context = getDisplayContext(); if (shared_context_handle_buffer != NULL) { PbufferInfo *shared_buffer_info = (PbufferInfo *)(*env)->GetDirectBufferAddress(env, shared_context_handle_buffer); @@ -156,18 +178,16 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreatePbuffer(JNIEnv PbufferInfo *buffer_info = (PbufferInfo *)(*env)->GetDirectBufferAddress(env, handle_buffer); bool result; result = createPbufferUsingUniqueContext(env, buffer_info, pixel_format, width, height, buffer_attribs, shared_context); - if (!result) { - decDisplay(); + if (!result) return; - } - if (!checkXError(env)) { + if (!checkXError(env, getDisplay())) { destroyPbuffer(buffer_info); return; } } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nMakePbufferCurrent - (JNIEnv *env, jobject this, jobject handle_buffer) + (JNIEnv *env, jclass clazz, jobject handle_buffer) { PbufferInfo *buffer_info = (PbufferInfo *)(*env)->GetDirectBufferAddress(env, handle_buffer); GLXPbuffer buffer = buffer_info->buffer; @@ -178,8 +198,8 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nMakePbufferCurrent } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyPbuffer - (JNIEnv *env, jobject this, jobject handle_buffer) + (JNIEnv *env, jclass clazz, jobject handle_buffer) { PbufferInfo *buffer_info = (PbufferInfo *)(*env)->GetDirectBufferAddress(env, handle_buffer); destroyPbuffer(buffer_info); -} +}*/